Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace CRA with Vite #315

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ user-guides/node_modules

# production
client/build
client/dist
user-guides/build

# misc
Expand Down
7 changes: 5 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Ignore artifacts:
build

client/build
client/dist
user-guides/guides
user-guides/build

publiccode.yml
# tell prettier to keep its hands off the bloody config files
client/vite.config.js
e2e/playwright.config.js
17 changes: 9 additions & 8 deletions client/public/index.html → client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
<meta name="description" content="Bed Availability Transport Study" />
<meta name="msapplication-TileColor" content="#425cc7" />

<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/apple-touch-icon.png" />
<link rel="mask-icon" href="%PUBLIC_URL%/safari-pinned-tab.svg" color="#425cc7" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="%PUBLIC_URL%/libraries/fontawesome-free/css/all.css" />
<link rel="stylesheet" href="%PUBLIC_URL%/libraries/uswds/theme/styles.css" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#425cc7" />
<link rel="manifest" href="/manifest.json" />
<link rel="stylesheet" href="/libraries/fontawesome-free/css/all.css" />
<link rel="stylesheet" href="/libraries/uswds/theme/styles.css" />

<script>
window.env = {};
Expand All @@ -30,5 +30,6 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="src/index.js"></script>
</body>
</html>
26 changes: 14 additions & 12 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.21.4",
"classnames": "^2.3.1",
"http-proxy-middleware": "^1.3.1",
"http-status-codes": "^1.4.0",
"luxon": "^1.28.0",
"postcss": "^8.4.14",
"postcss-cli": "^10.0.0",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand All @@ -22,18 +15,26 @@
"react-scripts": "5.0.1",
"react-use-websocket": "^2.9.1",
"sass": "^1.57.1",
"sass-loader": "^13.2.0",
"shared": "file:../shared",
"use-sound": "^4.0.1",
"uswds": "^2.13.3"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.14",
"esbuild": "^0.17.12",
"postcss": "^8.4.21",
"postcss-cli": "^10.0.0",
"vite": "^4.2.1",
"vite-plugin-svgr": "^2.4.0"
},
"scripts": {
"start": "react-scripts --openssl-legacy-provider start",
"build": "react-scripts --openssl-legacy-provider build && yarn sass --no-source-map && yarn postcss --no-map",
"start": "vite serve",
"build": "vite build",
"sass": "sass --load-path=../node_modules/uswds/dist/scss --style=compressed src/theme/styles.scss build/libraries/uswds/theme/styles_pre.css",
"postcss": "postcss --verbose build/libraries/uswds/theme/styles_pre.css --use autoprefixer -o build/libraries/uswds/theme/styles.css",
"test": "react-scripts test",
"eject": "react-scripts eject"
"test": "echo \"No client tests\" && exit 0"
},
"browserslist": {
"production": [
Expand Down Expand Up @@ -105,6 +106,7 @@
},
"ignorePatterns": [
"build",
"dist",
"node_modules"
]
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/Components/FormComboBox.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { comboBox } from '../../../node_modules/uswds/src/js/components';
import { comboBox } from 'uswds/src/js/components';

import { ValidationState } from '../Models/PatientFieldData';
import ValidationMessage from './ValidationMessage';
Expand Down
11 changes: 0 additions & 11 deletions client/src/setupProxy.js

This file was deleted.

6 changes: 3 additions & 3 deletions client/src/utils/convertToPropType.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const PropTypes = require('prop-types');
import PropTypes from 'prop-types';

const PropTypeLookup = {
text: 'string',
Expand All @@ -7,7 +7,7 @@ const PropTypeLookup = {
boolean: 'bool',
};

module.exports = function convertToPropType(field) {
export function convertToPropType(field) {
const { name, type, isParam, typeArgs, required } = field;
// if the field isn't something we want to convert to a propType, then return an empty array so
// getFieldHash() won't include this field
Expand All @@ -29,4 +29,4 @@ module.exports = function convertToPropType(field) {
}

return result;
};
}
82 changes: 82 additions & 0 deletions client/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import fs from 'node:fs';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
import * as esbuild from 'esbuild';

const SourceJSPattern = /\/src\/.*\.js$/;

// this plugin will force Vite to look for JSX in all .js files while building the production
// bundler, so we don't have to rename every single file
const rollupPlugin = (matchers) => ({
name: 'js-in-jsx',
load(id) {
if (matchers.some((matcher) => matcher.test(id))) {
const file = fs.readFileSync(id, { encoding: 'utf-8' });
return esbuild.transformSync(file, { loader: 'jsx' });
}
},
});

// proxy these routes to the server running on port 4000. this takes the place
// of setupProxy.js in webpack.
const proxy = ['/api', '/auth', '/libraries', '/wss'].reduce(
(result, route) => ({
...result,
[route]: {
target: 'http://localhost:4000',
changeOrigin: true,
ws: true,
},
}),
{}
);

export default defineConfig({
server: {
// vite defaults to an unused port, so force it to 3000
port: 3000,
// if port 3000 is being used, then quit (though it's not clear this actually works)
strict: true,
// no idea why this is necessary, but without it, the Vite dev server isn't reachable
// from a browser on the host machine
host: true,
proxy,
},
plugins: [
// raw SVG icons are imported in some places, so add a plugin so they get
// wrapped in a React component like in webpack
svgr(),
react(),
],
build: {
outDir: 'build',
rollupOptions: {
plugins: [
rollupPlugin([SourceJSPattern])
],
},
commonjsOptions: {
transformMixedEsModules: true,
},
},
optimizeDeps: {
include: [
'uswds',
'shared/constants',
'shared/metadata'
],
esbuildOptions: {
loader: {
'.js': 'jsx',
},
},
},
esbuild: {
// point the JSX parser at all .js files, so we don't have to rename them all to .jsx
loader: 'jsx',
include: [SourceJSPattern],
// we have to explicitly include this empty exclude key, for some reason
exclude: [],
},
});
2 changes: 1 addition & 1 deletion e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"dotenv": "^16.0.3"
},
"scripts": {
"test": "cd ../client && yarn build; cd ../e2e && DEBUG=pw:webserver playwright test",
"test": "yarn workspace client build && DEBUG=pw:webserver playwright test",
"install-chromium": "playwright install --with-deps chromium"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion e2e/playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const config = {

/* Run your local dev server before starting the tests */
webServer: {
command: 'cd ../server && yarn start:prod',
command: 'cd .. && yarn workspace server start:prod',
port: 3000,
reuseExistingServer: true,
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"eslint": "^8.33.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "^4.2.1",
Expand Down Expand Up @@ -106,6 +105,7 @@
},
"ignorePatterns": [
"build",
"dist",
"node_modules"
]
}
Expand Down
10 changes: 10 additions & 0 deletions shared/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ These files are shared by both the `client` and `server` packages. The `shared`
If you want to make a change in the shared code and then test it the client or server, run `yarn upgrade shared` from the root `/app` directory in the docker instance. This should cause yarn to copy the latest files from the `shared` package to the root `/node_modules/shared/` directory that's used by the client and server.

If you're making lots of changes to `shared` and want to quickly test them, using [`yarn link`](https://classic.yarnpkg.com/lang/en/docs/cli/link/) may be easier.

## Using `*` instead of `file:../shared` doesn't work

In theory, you should be able to add the `shared` package to others in the monorepo by adding `"shared": "*"` to their `package.json` files. This would link the package, so that any changes to `shared` would immediately be available in the other packages.

But using `*` instead of `file:../shared` causes a Rollup error during the build: `RollupError: "DeliveryStatus" is not exported by "../shared/constants/index.js", imported by "src/Models/Ringdown.js".`

This seems to be related to the fact that the `shared` package is in CJS format and has to get optimized during the dev serving process, thanks to the `optimizeDeps.include` array in the Vite config. But that during doesn't work during build, and various attempts at changing the `build.commonjsOptions` flags haven't worked. It also seems to be related to [this Vite bug](https://github.com/vitejs/vite/issues/2679).

So it seems simplest to use the `file:` format for specifying the version of `shared` for now, until it can get rewritten as an ES module. (Also note that you have to re-run yarn after making changes to the package.json file; otherwise things may look like they're working, even though they won't during CI/CD.)
2 changes: 1 addition & 1 deletion shared/constants/index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
exports.DeliveryStatus = require('./DeliveryStatus');
module.exports.DeliveryStatus = require('./DeliveryStatus');
4 changes: 4 additions & 0 deletions shared/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
constants: require('./constants'),
metadata: require('./metadata'),
};
8 changes: 7 additions & 1 deletion shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
"ModelMetadata.js",
"constants",
"metadata"
]
],
"exports": {
".": "./index.js",
"./constants": "./constants/index.js",
"./metadata": "./metadata/index.js",
"./metadata/*": "./metadata/*.js"
}
}
Loading