.. _react.start:

======================
Build the static files
======================

.. contents::
  :local:

Quick start
===========

We assume that you have installed a Lino :term:`developer environment` as
described in :ref:`dev.install`.

In case of problems during the following quick instructions, see
:ref:`react.npm.troubleshoot`.

Install NodeJS on your computer::

    $ sudo apt install nodejs npm

Get the latest stable Node.js version using the `n
<https://www.npmjs.com/package/n>`__ package::

  $ sudo npm install -g n
  $ sudo n stable

More precisely it is possible that you don't want the *latest* Node.js version.
The :file:`node_version.txt` contains the version for which the last build has
been run successfully::

  $ cat node_version.txt
  v24.12.0

Install the Lino React project into NodeJS::

    $ go react
    $ npm update
    $ npm install

Make your first build::

    $ npm run dev

Before pushing changes to the repository, run the :xfile:`build.sh` script::

    $ ./build.sh

Here is the content of this script::

    npm run build
    ln -s ../../../translations/extracts/i18n lino_react/react/static/react/locales
    git add lino_react/react/static/react/
    git add -u lino_react/react/config/react/main.html


See `How to prepare lino_react for commit`_ below.


How to prepare lino_react for commit
====================================

The Lino React repository includes the files that get generated by webpack when
you run :cmd:`npm run build`. If Lino React was a Node.js application we
wouldn't include them because they are just the result of :cmd:`npm run build`
command. But Lino React is a Python package, not a Node.js package. We don't
want to require a Lino production site to install the Node.js framework just to
build these files. That's why we let webpack generate these files into the
:xfile:`lino_react/react/static` directory where Django's
:manage:`collectstatic` command will find them.

Let's say you have done a one-line change in :xfile:`LinoComponents.jsx`, you
did several :cmd:`npm run dev` and finally a :cmd:`npm run build`. Now you want
to commit and push your changes. Here is how your :cmd:`git status` looks now::

  $ git st
  On branch master
  Changes not staged for commit:
    (use "git add/rm <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
          modified:   lino_react/react/components/LinoComponents.jsx
          modified:   lino_react/react/config/react/main.html
          deleted:    lino_react/react/static/react/main.LinoComponents_LinoDetail.3a2ba6c95a6a1ea45dfa.js
          deleted:    lino_react/react/static/react/main.LinoComponents_LinoDetail.3a2ba6c95a6a1ea45dfa.js.map
          deleted:    lino_react/react/static/react/main.runtime.0d5dac49c1a36c98c50a.js
          deleted:    lino_react/react/static/react/main.runtime.0d5dac49c1a36c98c50a.js.map

  Untracked files:
    (use "git add <file>..." to include in what will be committed)
          lino_react/react/static/react/main.LinoComponents_LinoDetail.d6be98efa3b7c0026319.js
          lino_react/react/static/react/main.LinoComponents_LinoDetail.d6be98efa3b7c0026319.js.map
          lino_react/react/static/react/main.runtime.91ad014441c6c21a0d74.js
          lino_react/react/static/react/main.runtime.91ad014441c6c21a0d74.js.map

  no changes added to commit (use "git add" and/or "git commit -a")

We can see that four files have been deleted and four similar files are new.
That's because each build uses a new hash in order to make sure the files are
not getting cached somewhere.

Rather than manually deleting the four files and then adding their new version,
you can :cmd:`git rm` the whole :file:`lino_react/react/static/react` directory,
run another build, and then :cmd:`git add` the whole directory back again::

  $ git rm -r lino_react/react/static/react
  $ npm run build
  $ git add lino_react/react/static/react

The :file:`static/react` directory contains more than 100 files, but most of
them get rebuilt exactly as before. Git detects that there is no difference and
so the :cmd:`git add` for these files automatically "cancels" the :cmd:`git rm`.
The result is that you have just two files deleted and two similar files added::

  $ git st
  On branch master
  Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
          deleted:    lino_react/react/static/react/main.LinoComponents_LinoDetail.3a2ba6c95a6a1ea45dfa.js
          deleted:    lino_react/react/static/react/main.LinoComponents_LinoDetail.3a2ba6c95a6a1ea45dfa.js.map
          new file:   lino_react/react/static/react/main.LinoComponents_LinoDetail.6acd0e3ccae181744860.js
          new file:   lino_react/react/static/react/main.LinoComponents_LinoDetail.6acd0e3ccae181744860.js.map
          renamed:    lino_react/react/static/react/main.runtime.0d5dac49c1a36c98c50a.js -> lino_react/react/static/react/main.runtime.1b037ddc1d1b089893ea.js
          renamed:    lino_react/react/static/react/main.runtime.0d5dac49c1a36c98c50a.js.map -> lino_react/react/static/react/main.runtime.1b037ddc1d1b089893ea.js.map

  Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
          modified:   lino_react/react/components/LinoComponents.jsx
          modified:   lino_react/react/config/react/main.html



.. xfile:: lino_react/react/static

  The files in this directory will be distributed with the Python package, and
  Django's :manage:`collectstatic` command on a :term:`Lino site` will find
  them.

  It contains two subdirectories:

  - :file:`react` is the output path for webpack where it stores minimized js
    code (see :xfile:`webpack.config.js`)

  - :file:`media` is also populated by webpack, from files other than
    JavaScript.
