This README contains the following content:
- Installing and running the client site
- Generating React components
- Linting and Formatting
- Testing
- Localization
- Feature toggling
- Environment variables
- Debugging
- Package versions
This will work for both MacOS and Win10. Follow instructions on this link. Be sure to read through the whole doc to find the sections within each step relevant to you (e.g. if you're using Homebrew, when you get to Step 2 look for the section, "Install NVM with Homebrew").
If you install NVM using Homebrew, make sure to read the output in terminal after you run brew install nvm
. You will need to add a few lines to your ~/.bash_profile and perhaps complete a couple other tasks.
Once you install NVM, don't forget to install Node! This is included in the linked tutorial above. This will also install npm
which you need for the steps below.
After you've downloaded the nvm and the latest node (using the above steps) also install node version 14 by:
nvm install 14
You should then be able to switch to that version of node by:
nvm use 14
To validate you are using node 14, type:
node -v
This should return Now using node 14.x.x (npm v6.x.x)
Install yarn if you do not have it yet. Open your terminal and run sudo npm install -global yarn
. This works on MacOS and Win10. To confirm it is installed, run yarn -v
. A version number should be returned.
- Navigate to the base directory of this repository, and go to the
client
directory (cd client
). - Run the command
npm install
to install the dependencies. - Run
npm start
to start up the client app. - Open your browser and navigate to http://localhost:8000
Note that while this app uses npm as the package manager, yarn is required to build the uswds library.
- Launch VS code in the top level directory (above client)
- Install the Microsoft docker VS code extension
- make sure you are in the main repo's directory
- Type
docker-compose up
- Running this on MacBook Pro with a 2.6GHz 6-core i7 with 16 GB of memory can take upto 20 minutes to complete.
- This will create three images, j4_website, j40_score_server and j40_data_pipeline. It will take up ~ 30 to 35 GB of image disk space
By navigating to the client folder, the Dockerfile runs npm start
. This will create a development version of the app.
If you've made changes to the docker-compose file and want to re-build the j40_website:
docker-compose build --no-cache j40_website
This will not use the cache and re-build the image. Then do
docker-compoe up
- Ensure that there's enough disk image space in docker. The Docker Desktop app will show the total disk image used (gear cog -> Resources -> Disk image size). This application will require ~ 30 - 35 GB. Allocating 50-60 GB should be sufficient. If the amount used is significantly greater than 35 GB you may need to prune the docker images:
docker image system
This should reduce the total used space.
If you don't want to use the local data-pipeline location for getting the tile / map layers, you can change the DATA_SOURCE env variable in the docker-compose.yml. See environment variables for more info.
- If an error is thrown about running out of space on device see this for ways to reclaim space.
See VIEW_MAP_DATA.md for more details on this.
Each React component requires a barrell, test, sass file and sass types file. You can run the auto-generated component to ensure you are following the style guide on creating React component for J40.
Please see this README for more information
This project uses ESLint for code linting and Prettier for formatting. They are integrated via gatsby-plugin-prettier-eslint.
Linting is a required check before merges can happen, please lint your code, for the sake of consistency!
To use:
-
During development:
npx gatsby develop
will automatically run prettier and eslint during development as files change, watch the console for updates.- Alternatively, if you're using VSCode:
-
Before a PR:
npm run lint:fix
can be run locally to apply auto-fixes to issues that can be fixed -
Before merge (automatic):
npm run lint
is run against all PRs by a github action.
The ruleset is simply the base ruleset + Google.
This project uses jest for unit testing, using react-test-renderer
to output to text-based snapshot files.
To run tests: npm test
To rebuild snapshots when you know a component has changed: npm run test:update
The app has end-to-end tests using cypress which can be started by:
npm run cy:open
This will open the test runner. Choose any tests to run!
This project uses Gatsby Plugin Intl to manage internationalization and localization.
There are a number of components to this, but for the purposes of localization, this utizes the popular react-intl
package from FormatJS.
This works by directing users to a locale-appropriate version of the page they wish to visit based on their browser settings, populated automatically at build time by the contents of json
files in the src/intl
directory.
For this library to work optimally, the following principles should be obeyed (see here for more detail):
- All user-visible strings should be wrapped with the
intl.formatMessage
function or the<FormattedMessage>
tag, with adescription
anddefaultMessage
set. Do not yet set the "id" tag, it will be generated for you. To generate files for localization, runnpm run intl:extract
to update the file atsrc/intl/en.json
with the extracted contents of allFormattedMessage
components. - Take note of the
id
in this file, and add this back as a parameter of your function/prop for your component (this is done to avoid naming collisions as detailed here) - All
Link
components should be imported fromgatsby-plugin-intl
instead to get the locale-appropriate link - All pages should import and use
useIntl
fromgatsby-plugin-intl
We will later add integration with Github Actions to ensure that all messages have been formatted as a condition/check for committed code.
From there, send src/intl/en.json
to translators. (Depending on the TMS (Translation Management System) in use, we may need a different format, so we can alter the settings in package.json
if needbe). When they return with the other language file, e.g. es.json
, place this in src/intl/
as a sibling to en.json
.
React-Intl
works according to Google SEO best practices by creating locale-specific URLs.
To access a translated version of a page, e.g. pages/index.js
, add the locale as a portion of the URL path, as follows:
- English:
localhost:8000/en/
, orlocalhost:8000/
(the default fallback is English)
There are 3 environment variables that can be set:
- DATA_SOURCE (required) = can be set to 'cdn' or 'local'. This is used to change where the tiles are sourced from. It is used in the constants file to determine which TILE_BASE_URL to use.
- SITE_URL = set this to change the base URL for the website's public html folder. If none is provided, then localhost:8000 is used. This is used for the site_map.xml file and robots.txt file. This is only used during production build aka
npm build
. - PATH_PREFIX = set this to add an additional path(s) to SITE_URL. If none is provided then no additional paths are added to the SITE_URL. This is only used during production build aka
npm build
.
Note when setting environment variables in docker-compose, DATA_SOURCE is the only one that is applicable.
We have implemented very simple feature flagging for this app, accessible via URL parameters.
There are a lot of benefits to using feature toggles -- see Martin Fowler for a longer justification, but in short, they enable shipping in-progress work to production without enabling particular features for all users.
To view features, add the flags
parameter to the URL, and set the value to a comma-delimited list of features to enable, e.g. localhost:8000?flags=1,2,3
will enable features 1, 2, and 3.
In the future we may add other means of audience-targeting, but for now we will be sharing links with flags enabled as a means of sharing in-development funcitonality
When developing, to use a flag:
- Pass the Gatsby-provided
location
variable to your component. You have several options here:- If your page uses the
Layout
component, you automatically getURLFlagProvider
(see FlagContext for more info). - If your page does not use
Layout
, you need to surround your component with aURLFlagProvider
component and passlocation
. You can getlocation
from the default props of the page (more here). See Index.tsx for an example.
- If your page uses the
- Use the
useFlags()
hook to get access to an array of flags, and check this array for the presence of the correct feature identifier. See J40Header for an example.
- The feature is an experimental change
- The feature is an outcome of a spike where the direct work wasn’t prioritized in the current sprint however there's a desire to help design to see / use it - eg. fullscreen / geolocation (future sprint purposes)
- The feature is something with multiple possible implementations that we want to give our team the experience of trying out separately for comparison purposes - eg. mapbox vs. openlayers, different low tile layers for low zoom
- Ensure that VS code is open in the client folder
- Run the app with
npm start
in the terminal - Click on the debugger (SHIFT+CMD+D on mac)
- Run the Debug Chrome configuration by hitting the green play button
- Install the CORS chrome extension in the browser that is launched by the debugger.
- Set breakpoints in VS code!
The following attemps to explain why certain packages versions have been chosen and what their current limitations are
package | current version | latest version | using latest? | how does it break? |
---|---|---|---|---|
gatsby | 3.14.6 | 4.14.2 | No | when attempting to update - breaks all unit tests. Compatibility warning come up with all plugins but this doesn't seems to effect functionality. This is the latest version we can release without investigating unit tests. |
gatsby-cli | 3.14.2 | 4.15.2 | No | when attempting to update - breaks all unit tests. Compatibility warning come up with all plugins but this doesn't seems to effect functionality. This is the latest version we can release without investigating unit tests. |
sass | 1.32.12 | 1.52.3 | No | This version is needed to surpress the dart warnings on / as division for each component. See here for more information |
uswds | 2.13.3 | 3.0.2 | No | Needs to stay at 2.13.3 for peer dependency on trussworks |
trussworks | 3.1.0 | 3.1.0 | No | latest! |