Unverified Commit fe22d6ae authored by Andrey Azov's avatar Andrey Azov Committed by GitHub
Browse files

Upgrade webpack to v5 (#362)

parent 09cba961
Pipeline #142590 passed with stages
in 8 minutes and 33 seconds
...@@ -20,10 +20,11 @@ variables: ...@@ -20,10 +20,11 @@ variables:
# Template to build static assets # Template to build static assets
.build-static: .build-static:
stage: test_build_static stage: test_build_static
image: node:12.13.0 image: node:14.16.0
before_script: before_script:
- cd src/ensembl - cd src/ensembl
- npm install --global npm@7.7.4
- npm ci - npm ci
script: script:
...@@ -147,7 +148,7 @@ variables: ...@@ -147,7 +148,7 @@ variables:
- kubectl apply -f ensembl-client-caas-deploy/ensembl_client_deployment.yaml - kubectl apply -f ensembl-client-caas-deploy/ensembl_client_deployment.yaml
Test: Test:
image: node:12.13.0 image: node:14.16.0
stage: test stage: test
before_script: before_script:
...@@ -448,4 +449,4 @@ stop_review: ...@@ -448,4 +449,4 @@ stop_review:
except: except:
- dev - dev
- master - master
- /^nodeploy\/.*$/ - /^nodeploy\/.*$/
\ No newline at end of file
...@@ -24,12 +24,13 @@ module.exports = { ...@@ -24,12 +24,13 @@ module.exports = {
"@typescript-eslint/explicit-module-boundary-types": 0, "@typescript-eslint/explicit-module-boundary-types": 0,
'@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 0, '@typescript-eslint/no-use-before-define': 0,
'@typescript-eslint/no-unused-vars': ['warn', { args: 'after-used' }],
'react/display-name': 0, 'react/display-name': 0,
'react/prop-types': 0, 'react/prop-types': 0,
'react/no-unescaped-entities': 0, 'react/no-unescaped-entities': 0,
'react-hooks/rules-of-hooks': 2, 'react-hooks/rules-of-hooks': 2,
'prettier/prettier': 0, 'prettier/prettier': 0,
'no-unused-vars': ['warn', { args: 'after-used' }], "no-unused-vars": "off",
'no-unneeded-ternary': 'error', 'no-unneeded-ternary': 'error',
'eqeqeq': 'error' 'eqeqeq': 'error'
}, },
......
const webpackConfig = require('./webpack'); const webpackConfig = require('./webpack');
module.exports = { module.exports = {
core: {
builder: "webpack5",
},
stories: ['../stories/**/*.stories.tsx'], stories: ['../stories/**/*.stories.tsx'],
webpackFinal: (config) => webpackConfig(config), webpackFinal: (config) => webpackConfig(config),
addons: [ addons: [
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
*/ */
const path = require('path'); const path = require('path');
const postcssPresetEnv = require('postcss-preset-env');
module.exports = (config) => { module.exports = (config) => {
......
FROM node:10.15.1 FROM node:14.16.0
ARG SOURCE_DIR="./" ARG SOURCE_DIR="./"
...@@ -8,5 +8,6 @@ COPY ${SOURCE_DIR} /srv/ensembl-client/ ...@@ -8,5 +8,6 @@ COPY ${SOURCE_DIR} /srv/ensembl-client/
# NOTE: NODE_ENV=development before npm install ensures that dev dependencies won't get skipped # NOTE: NODE_ENV=development before npm install ensures that dev dependencies won't get skipped
RUN cd /srv/ensembl-client/ && \ RUN cd /srv/ensembl-client/ && \
NODE_ENV=development npm install && \ npm install --global npm@7.6.2 && \
npm ci && \
npm run test npm run test
This diff is collapsed.
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
"scripts": { "scripts": {
"copy-dotenv": "test ! -f .env && (cp .env.example .env; echo '.env file created') || true", "copy-dotenv": "test ! -f .env && (cp .env.example .env; echo '.env file created') || true",
"start": "npm install --no-save && npm run serve:dev", "start": "npm install --no-save && npm run serve:dev",
"serve:dev": "npm run copy-dotenv && webpack-dev-server --config ./webpack/webpack.config.js --env.mode dev", "serve:dev": "npm run copy-dotenv && webpack serve --config ./webpack/webpack.config.js --env dev",
"serve:prod": "node ./server.js", "serve:prod": "node ./server.js",
"serve:prod:secure": "node ./server.js -p https", "serve:prod:secure": "node ./server.js -p https",
"build": "rimraf ./dist && NODE_ENV=production webpack --config ./webpack/webpack.config.js --env.mode prod", "build": "rimraf ./dist && NODE_ENV=production webpack --config ./webpack/webpack.config.js --env prod --progress profile",
"prod:analyse": "npm run build -- --env.presets analyse", "prod:analyse": "npm run build -- --analyze",
"certify": "node setup-ssl", "certify": "node setup-ssl",
"lint": "npm run lint:scripts && npm run lint:styles", "lint": "npm run lint:scripts && npm run lint:styles",
"lint:scripts": "eslint 'src/**/*.{ts,tsx}'", "lint:scripts": "eslint 'src/**/*.{ts,tsx}'",
...@@ -52,16 +52,16 @@ ...@@ -52,16 +52,16 @@
"@reduxjs/toolkit": "1.4.0", "@reduxjs/toolkit": "1.4.0",
"@sentry/browser": "5.25.0", "@sentry/browser": "5.25.0",
"classnames": "2.2.6", "classnames": "2.2.6",
"comlink": "4.3.0",
"connected-react-router": "6.8.0", "connected-react-router": "6.8.0",
"core-js": "3.6.5", "core-js": "3.6.5",
"d3": "6.2.0", "d3": "6.2.0",
"dotenv": "8.2.0", "dotenv": "8.2.0",
"ensembl-genome-browser": "https://raw.githubusercontent.com/Ensembl/ensembl-genome-browser-assets/master/assets-80f51620ed443c640cdfd6b5aebd505b.tar.gz", "ensembl-genome-browser": "https://raw.githubusercontent.com/Ensembl/ensembl-genome-browser-assets/master/assets-80f51620ed443c640cdfd6b5aebd505b.tar.gz",
"graphql": "15.3.0", "graphql": "15.3.0",
"koa-proxy": "1.0.0-alpha.3",
"lodash": "4.17.20", "lodash": "4.17.20",
"query-string": "6.13.5", "query-string": "6.13.5",
"react": "16.13.1", "react": "16.14.0",
"react-cookie": "4.0.3", "react-cookie": "4.0.3",
"react-dom": "16.13.1", "react-dom": "16.13.1",
"react-ga": "3.1.2", "react-ga": "3.1.2",
...@@ -76,21 +76,22 @@ ...@@ -76,21 +76,22 @@
"what-input": "5.2.10" "what-input": "5.2.10"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.11.6", "@babel/core": "7.13.8",
"@babel/plugin-proposal-class-properties": "7.10.4", "@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4", "@babel/plugin-proposal-nullish-coalescing-operator": "7.13.8",
"@babel/plugin-proposal-object-rest-spread": "7.11.0", "@babel/plugin-proposal-object-rest-spread": "7.13.8",
"@babel/plugin-proposal-optional-chaining": "7.11.0", "@babel/plugin-proposal-optional-chaining": "7.13.8",
"@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.10.4", "@babel/plugin-transform-modules-commonjs": "7.13.8",
"@babel/preset-env": "7.11.5", "@babel/preset-env": "7.13.9",
"@babel/preset-react": "7.10.4", "@babel/preset-react": "7.12.13",
"@babel/preset-typescript": "7.10.4", "@babel/preset-typescript": "7.13.0",
"@storybook/addon-essentials": "6.0.26", "@storybook/addon-essentials": "6.2.0-rc.8",
"@storybook/addons": "6.0.26", "@storybook/addons": "6.2.0-rc.8",
"@storybook/react": "6.0.26", "@storybook/builder-webpack5": "6.2.0-rc.8",
"@storybook/theming": "6.0.26", "@storybook/react": "6.2.0-rc.8",
"@svgr/webpack": "5.4.0", "@storybook/theming": "6.2.0-rc.8",
"@svgr/webpack": "5.5.0",
"@testing-library/jest-dom": "5.11.6", "@testing-library/jest-dom": "5.11.6",
"@testing-library/react": "11.2.2", "@testing-library/react": "11.2.2",
"@testing-library/user-event": "12.2.2", "@testing-library/user-event": "12.2.2",
...@@ -109,19 +110,18 @@ ...@@ -109,19 +110,18 @@
"@types/react-router-dom": "5.1.6", "@types/react-router-dom": "5.1.6",
"@types/react-router-hash-link": "1.2.1", "@types/react-router-hash-link": "1.2.1",
"@types/redux-mock-store": "1.0.2", "@types/redux-mock-store": "1.0.2",
"@types/webpack-env": "1.15.2", "@types/webpack-env": "1.16.0",
"@typescript-eslint/eslint-plugin": "4.4.0", "@typescript-eslint/eslint-plugin": "4.16.1",
"@typescript-eslint/parser": "4.4.0", "@typescript-eslint/parser": "4.16.1",
"babel-core": "7.0.0-bridge.0", "babel-core": "7.0.0-bridge.0",
"babel-jest": "26.5.2", "babel-jest": "26.6.3",
"babel-loader": "8.1.0", "babel-loader": "8.2.2",
"babel-plugin-react-remove-properties": "0.3.0", "babel-plugin-react-remove-properties": "0.3.0",
"brotli-webpack-plugin": "1.1.0", "compression-webpack-plugin": "7.1.2",
"comlink": "4.3.0",
"compression-webpack-plugin": "5.0.2",
"connect-history-api-fallback": "1.6.0", "connect-history-api-fallback": "1.6.0",
"copy-webpack-plugin": "6.1.0", "copy-webpack-plugin": "8.1.0",
"css-loader": "4.3.0", "css-loader": "5.1.4",
"css-minimizer-webpack-plugin": "1.3.0",
"enzyme": "3.11.0", "enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.5", "enzyme-adapter-react-16": "1.15.5",
"enzyme-to-json": "3.6.1", "enzyme-to-json": "3.6.1",
...@@ -130,49 +130,47 @@ ...@@ -130,49 +130,47 @@
"eslint-plugin-prettier": "3.1.4", "eslint-plugin-prettier": "3.1.4",
"eslint-plugin-react": "7.21.4", "eslint-plugin-react": "7.21.4",
"eslint-plugin-react-hooks": "4.1.2", "eslint-plugin-react-hooks": "4.1.2",
"faker": "5.1.0", "faker": "5.4.0",
"file-loader": "6.1.0", "file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "5.1.0", "fork-ts-checker-webpack-plugin": "6.2.0",
"gh-pages": "3.1.0", "gh-pages": "3.1.0",
"html-webpack-plugin": "4.4.1", "html-webpack-plugin": "5.3.1",
"husky": "4.3.0", "husky": "4.3.0",
"identity-obj-proxy": "3.0.0", "identity-obj-proxy": "3.0.0",
"image-webpack-loader": "6.0.0", "image-webpack-loader": "7.0.1",
"jest": "26.5.3", "jest": "26.5.3",
"jest-fetch-mock": "3.0.3", "jest-fetch-mock": "3.0.3",
"jest-transform-stub": "2.0.0", "jest-transform-stub": "2.0.0",
"koa": "2.13.0", "koa": "2.13.0",
"koa-connect": "2.1.0", "koa-connect": "2.1.0",
"koa-proxy": "1.0.0-alpha.3",
"koa-static": "5.0.0", "koa-static": "5.0.0",
"licence-manager": "git+https://github.com/Ensembl/ensembl-licence-manager.git#36b534d28ff26d345b4ba4da0cbc18e1e0f7a6b7", "licence-manager": "git+https://github.com/Ensembl/ensembl-licence-manager.git#36b534d28ff26d345b4ba4da0cbc18e1e0f7a6b7",
"lint-staged": "10.4.0", "lint-staged": "10.4.0",
"mini-css-extract-plugin": "0.11.1", "mini-css-extract-plugin": "1.3.9",
"node-sass": "4.14.1", "node-sass": "5.0.0",
"optimize-css-assets-webpack-plugin": "5.0.4", "postcss": "8.2.8",
"postcss": "7.0.32", "postcss-loader": "5.2.0",
"postcss-loader": "4.0.1",
"postcss-preset-env": "6.7.0", "postcss-preset-env": "6.7.0",
"prettier": "2.1.2", "prettier": "2.1.2",
"redux-mock-store": "1.5.4", "redux-mock-store": "1.5.4",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"robotstxt-webpack-plugin": "7.0.0", "sass-loader": "11.0.1",
"sass-loader": "10.0.2", "source-map-loader": "2.0.1",
"source-map-loader": "1.1.0", "style-loader": "2.0.0",
"style-loader": "1.2.1",
"stylelint": "13.7.2", "stylelint": "13.7.2",
"stylelint-config-recommended-scss": "4.2.0", "stylelint-config-recommended-scss": "4.2.0",
"stylelint-scss": "3.18.0", "stylelint-scss": "3.18.0",
"stylelint-webpack-plugin": "2.1.0", "stylelint-webpack-plugin": "2.1.1",
"terser-webpack-plugin": "4.1.0",
"ts-multipick": "1.0.0", "ts-multipick": "1.0.0",
"typescript": "4.0.3", "typescript": "4.0.3",
"webpack": "4.44.1", "webpack": "5.28.0",
"webpack-bundle-analyzer": "3.8.0", "webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "3.3.12", "webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.0", "webpack-dev-server": "3.11.2",
"webpack-merge": "5.1.4", "webpack-merge": "5.7.3",
"workbox-webpack-plugin": "5.1.4", "workbox-webpack-plugin": "6.1.2",
"worker-plugin": "5.0.0" "worker-loader": "3.0.8"
}, },
"browserslist": [ "browserslist": [
"> 1% and last 2 versions", "> 1% and last 2 versions",
......
module.exports = {
policy: [{ userAgent: '*', disallow: '/' }]
};
...@@ -27,7 +27,8 @@ import { ...@@ -27,7 +27,8 @@ import {
TranscriptSequenceMetadata TranscriptSequenceMetadata
} from './fetchSequenceChecksums'; } from './fetchSequenceChecksums';
import { // @ts-expect-error There is in fact no default export in the worker
import SequenceFetcherWorker, {
WorkerApi, WorkerApi,
SingleSequenceFetchParams SingleSequenceFetchParams
} from 'src/shared/workers/sequenceFetcher.worker'; } from 'src/shared/workers/sequenceFetcher.worker';
...@@ -50,9 +51,7 @@ export const fetchForProtein = async (payload: FetchPayload) => { ...@@ -50,9 +51,7 @@ export const fetchForProtein = async (payload: FetchPayload) => {
options options
}); });
const worker = new Worker('src/shared/workers/sequenceFetcher.worker', { const worker = new SequenceFetcherWorker();
type: 'module'
});
const service = wrap<WorkerApi>(worker); const service = wrap<WorkerApi>(worker);
......
...@@ -29,7 +29,8 @@ import { ...@@ -29,7 +29,8 @@ import {
TranscriptSequenceMetadata TranscriptSequenceMetadata
} from './fetchSequenceChecksums'; } from './fetchSequenceChecksums';
import { // @ts-expect-error There is in fact no default export in the worker
import SequenceFetcherWorker, {
WorkerApi, WorkerApi,
SingleSequenceFetchParams SingleSequenceFetchParams
} from 'src/shared/workers/sequenceFetcher.worker'; } from 'src/shared/workers/sequenceFetcher.worker';
...@@ -74,9 +75,7 @@ export const fetchForTranscript = async (payload: FetchPayload) => { ...@@ -74,9 +75,7 @@ export const fetchForTranscript = async (payload: FetchPayload) => {
); );
} }
const worker = new Worker('src/shared/workers/sequenceFetcher.worker', { const worker = new SequenceFetcherWorker();
type: 'module'
});
const service = wrap<WorkerApi>(worker); const service = wrap<WorkerApi>(worker);
......
User-agent: *
Disallow: /
const isDevelopment = (environment) => ['dev', 'development'].includes(environment);
module.exports = {
isDevelopment
};
...@@ -2,15 +2,12 @@ const path = require('path'); ...@@ -2,15 +2,12 @@ const path = require('path');
const HtmlPlugin = require('html-webpack-plugin'); const HtmlPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin'); const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
const WorkerPlugin = require("worker-plugin");
const { getPaths } = require('../paths'); const { getPaths } = require('../paths');
const { isDevelopment } = require('./environment-detector');
module.exports = (env) => { module.exports = (env) => {
const isDev = isDevelopment(env.mode); const isDev = env.dev;
const paths = getPaths(); const paths = getPaths();
return { return {
// the starting point of webpack bundling // the starting point of webpack bundling
entry: { entry: {
...@@ -19,6 +16,13 @@ module.exports = (env) => { ...@@ -19,6 +16,13 @@ module.exports = (env) => {
module: { module: {
rules: [ rules: [
{
test: /\.worker\.ts$/,
use: [
{ loader: "worker-loader" },
{ loader: 'babel-loader' }
],
},
{ {
test: /.tsx?$/, test: /.tsx?$/,
loader: 'babel-loader', loader: 'babel-loader',
...@@ -67,9 +71,9 @@ module.exports = (env) => { ...@@ -67,9 +71,9 @@ module.exports = (env) => {
}, },
// prevent webpack from searching fs (node API) to load the web assembly files // prevent webpack from searching fs (node API) to load the web assembly files
node: { // node: {
fs: 'empty' // fs: 'empty'
}, // },
// this is the config to define how the output files needs to be // this is the config to define how the output files needs to be
output: { output: {
...@@ -96,10 +100,9 @@ module.exports = (env) => { ...@@ -96,10 +100,9 @@ module.exports = (env) => {
// in prod, path for saving static assets is dist/static/, and index.html has to be saved top-level in the dist folder // in prod, path for saving static assets is dist/static/, and index.html has to be saved top-level in the dist folder
filename: isDev ? 'index.html' : '../index.html', filename: isDev ? 'index.html' : '../index.html',
template: paths.htmlTemplatePath, template: paths.htmlTemplatePath,
publicPath: '/' publicPath: isDev ? '/' : '/static'
}), })
new WorkerPlugin()
], ],
// configuration that allows us to not to use file extensions and shorten import paths (using aliases) // configuration that allows us to not to use file extensions and shorten import paths (using aliases)
...@@ -109,7 +112,9 @@ module.exports = (env) => { ...@@ -109,7 +112,9 @@ module.exports = (env) => {
config: path.join(paths.rootPath, 'config.ts'), config: path.join(paths.rootPath, 'config.ts'),
src: path.join(paths.rootPath, 'src'), src: path.join(paths.rootPath, 'src'),
tests: path.join(paths.rootPath, 'tests'), tests: path.join(paths.rootPath, 'tests'),
static: path.join(paths.rootPath, 'static') static: path.join(paths.rootPath, 'static'),
fs: false,
path: false
} }
} }
} }
......
...@@ -61,7 +61,7 @@ const devServerConfig = { ...@@ -61,7 +61,7 @@ const devServerConfig = {
// concatenate the common config with the dev config // concatenate the common config with the dev config
module.exports = () => ({ module.exports = () => ({
mode: 'development', mode: 'development',
devtool: 'cheap-module-eval-source-map', devtool: 'eval-cheap-module-source-map',
module: { module: {
rules: [ rules: [
// this is the loader that will make webpack load file formats that are not supported by other loaders // this is the loader that will make webpack load file formats that are not supported by other loaders
......
const webpack = require('webpack'); const webpack = require('webpack');
const path = require('path'); const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin');
const BrotliPlugin = require('brotli-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin'); const WorkboxPlugin = require('workbox-webpack-plugin');
const RobotstxtPlugin = require('robotstxt-webpack-plugin');
const { getPaths } = require('../paths'); const { getPaths } = require('../paths');
const paths = getPaths('production'); const paths = getPaths('production');
// copy from the environment the same variables that are declared in .env.example // copy from the environment the same variables that are declared in .env.example
// NOTE: if no environment variable with corresponding key is present, the value from .env.example will be used // NOTE: if no environment variable with corresponding key is present, the value from .env.example will be used
const dotenv = require('dotenv').config({ const dotenv = require('dotenv').config({
...@@ -76,36 +73,35 @@ module.exports = () => { ...@@ -76,36 +73,35 @@ module.exports = () => {
patterns: [ patterns: [
{ {
from: path.join(paths.nodeModulesPath, 'ensembl-genome-browser/browser*.wasm'), from: path.join(paths.nodeModulesPath, 'ensembl-genome-browser/browser*.wasm'),
to: path.join(paths.buildStaticPath, 'browser'), to: path.join(paths.buildStaticPath, 'browser', '[name][ext]')
flatten: true
}, },
{ {
from: path.join(paths.staticPath, 'favicons/*'), from: path.join(paths.staticPath, 'favicons/*'),
to: path.join(paths.buildStaticPath, 'favicons'), to: path.join(paths.buildStaticPath, 'favicons', '[name][ext]')
flatten: true
}, },
{ {
from: path.join(paths.staticPath, 'manifest.json'), from: path.join(paths.staticPath, 'manifest.json'),
to: paths.buildStaticPath, to: path.join(paths.buildStaticPath, '[name][ext]')
flatten: true },
{
from: path.join(paths.staticPath, 'robots.txt'),
to: paths.buildPath
} }
] ]
}), }),
// generate unique hashes for files based on the relative paths // compress static files 5kB and larger
new webpack.HashedModuleIdsPlugin(),