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:
# Template to build static assets
.build-static:
stage: test_build_static
image: node:12.13.0
image: node:14.16.0
before_script:
- cd src/ensembl
- npm install --global npm@7.7.4
- npm ci
script:
......@@ -147,7 +148,7 @@ variables:
- kubectl apply -f ensembl-client-caas-deploy/ensembl_client_deployment.yaml
Test:
image: node:12.13.0
image: node:14.16.0
stage: test
before_script:
......@@ -448,4 +449,4 @@ stop_review:
except:
- dev
- master
- /^nodeploy\/.*$/
\ No newline at end of file
- /^nodeploy\/.*$/
......@@ -24,12 +24,13 @@ module.exports = {
"@typescript-eslint/explicit-module-boundary-types": 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 0,
'@typescript-eslint/no-unused-vars': ['warn', { args: 'after-used' }],
'react/display-name': 0,
'react/prop-types': 0,
'react/no-unescaped-entities': 0,
'react-hooks/rules-of-hooks': 2,
'prettier/prettier': 0,
'no-unused-vars': ['warn', { args: 'after-used' }],
"no-unused-vars": "off",
'no-unneeded-ternary': 'error',
'eqeqeq': 'error'
},
......
const webpackConfig = require('./webpack');
module.exports = {
core: {
builder: "webpack5",
},
stories: ['../stories/**/*.stories.tsx'],
webpackFinal: (config) => webpackConfig(config),
addons: [
......
......@@ -3,7 +3,6 @@
*/
const path = require('path');
const postcssPresetEnv = require('postcss-preset-env');
module.exports = (config) => {
......
FROM node:10.15.1
FROM node:14.16.0
ARG SOURCE_DIR="./"
......@@ -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
RUN cd /srv/ensembl-client/ && \
NODE_ENV=development npm install && \
npm install --global npm@7.6.2 && \
npm ci && \
npm run test
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -15,11 +15,11 @@
"scripts": {
"copy-dotenv": "test ! -f .env && (cp .env.example .env; echo '.env file created') || true",
"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:secure": "node ./server.js -p https",
"build": "rimraf ./dist && NODE_ENV=production webpack --config ./webpack/webpack.config.js --env.mode prod",
"prod:analyse": "npm run build -- --env.presets analyse",
"build": "rimraf ./dist && NODE_ENV=production webpack --config ./webpack/webpack.config.js --env prod --progress profile",
"prod:analyse": "npm run build -- --analyze",
"certify": "node setup-ssl",
"lint": "npm run lint:scripts && npm run lint:styles",
"lint:scripts": "eslint 'src/**/*.{ts,tsx}'",
......@@ -52,16 +52,16 @@
"@reduxjs/toolkit": "1.4.0",
"@sentry/browser": "5.25.0",
"classnames": "2.2.6",
"comlink": "4.3.0",
"connected-react-router": "6.8.0",
"core-js": "3.6.5",
"d3": "6.2.0",
"dotenv": "8.2.0",
"ensembl-genome-browser": "https://raw.githubusercontent.com/Ensembl/ensembl-genome-browser-assets/master/assets-80f51620ed443c640cdfd6b5aebd505b.tar.gz",
"graphql": "15.3.0",
"koa-proxy": "1.0.0-alpha.3",
"lodash": "4.17.20",
"query-string": "6.13.5",
"react": "16.13.1",
"react": "16.14.0",
"react-cookie": "4.0.3",
"react-dom": "16.13.1",
"react-ga": "3.1.2",
......@@ -76,21 +76,22 @@
"what-input": "5.2.10"
},
"devDependencies": {
"@babel/core": "7.11.6",
"@babel/plugin-proposal-class-properties": "7.10.4",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4",
"@babel/plugin-proposal-object-rest-spread": "7.11.0",
"@babel/plugin-proposal-optional-chaining": "7.11.0",
"@babel/core": "7.13.8",
"@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.13.8",
"@babel/plugin-proposal-object-rest-spread": "7.13.8",
"@babel/plugin-proposal-optional-chaining": "7.13.8",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.10.4",
"@babel/preset-env": "7.11.5",
"@babel/preset-react": "7.10.4",
"@babel/preset-typescript": "7.10.4",
"@storybook/addon-essentials": "6.0.26",
"@storybook/addons": "6.0.26",
"@storybook/react": "6.0.26",
"@storybook/theming": "6.0.26",
"@svgr/webpack": "5.4.0",
"@babel/plugin-transform-modules-commonjs": "7.13.8",
"@babel/preset-env": "7.13.9",
"@babel/preset-react": "7.12.13",
"@babel/preset-typescript": "7.13.0",
"@storybook/addon-essentials": "6.2.0-rc.8",
"@storybook/addons": "6.2.0-rc.8",
"@storybook/builder-webpack5": "6.2.0-rc.8",
"@storybook/react": "6.2.0-rc.8",
"@storybook/theming": "6.2.0-rc.8",
"@svgr/webpack": "5.5.0",
"@testing-library/jest-dom": "5.11.6",
"@testing-library/react": "11.2.2",
"@testing-library/user-event": "12.2.2",
......@@ -109,19 +110,18 @@
"@types/react-router-dom": "5.1.6",
"@types/react-router-hash-link": "1.2.1",
"@types/redux-mock-store": "1.0.2",
"@types/webpack-env": "1.15.2",
"@typescript-eslint/eslint-plugin": "4.4.0",
"@typescript-eslint/parser": "4.4.0",
"@types/webpack-env": "1.16.0",
"@typescript-eslint/eslint-plugin": "4.16.1",
"@typescript-eslint/parser": "4.16.1",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "26.5.2",
"babel-loader": "8.1.0",
"babel-jest": "26.6.3",
"babel-loader": "8.2.2",
"babel-plugin-react-remove-properties": "0.3.0",
"brotli-webpack-plugin": "1.1.0",
"comlink": "4.3.0",
"compression-webpack-plugin": "5.0.2",
"compression-webpack-plugin": "7.1.2",
"connect-history-api-fallback": "1.6.0",
"copy-webpack-plugin": "6.1.0",
"css-loader": "4.3.0",
"copy-webpack-plugin": "8.1.0",
"css-loader": "5.1.4",
"css-minimizer-webpack-plugin": "1.3.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.5",
"enzyme-to-json": "3.6.1",
......@@ -130,49 +130,47 @@
"eslint-plugin-prettier": "3.1.4",
"eslint-plugin-react": "7.21.4",
"eslint-plugin-react-hooks": "4.1.2",
"faker": "5.1.0",
"file-loader": "6.1.0",
"fork-ts-checker-webpack-plugin": "5.1.0",
"faker": "5.4.0",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "6.2.0",
"gh-pages": "3.1.0",
"html-webpack-plugin": "4.4.1",
"html-webpack-plugin": "5.3.1",
"husky": "4.3.0",
"identity-obj-proxy": "3.0.0",
"image-webpack-loader": "6.0.0",
"image-webpack-loader": "7.0.1",
"jest": "26.5.3",
"jest-fetch-mock": "3.0.3",
"jest-transform-stub": "2.0.0",
"koa": "2.13.0",
"koa-connect": "2.1.0",
"koa-proxy": "1.0.0-alpha.3",
"koa-static": "5.0.0",
"licence-manager": "git+https://github.com/Ensembl/ensembl-licence-manager.git#36b534d28ff26d345b4ba4da0cbc18e1e0f7a6b7",
"lint-staged": "10.4.0",
"mini-css-extract-plugin": "0.11.1",
"node-sass": "4.14.1",
"optimize-css-assets-webpack-plugin": "5.0.4",
"postcss": "7.0.32",
"postcss-loader": "4.0.1",
"mini-css-extract-plugin": "1.3.9",
"node-sass": "5.0.0",
"postcss": "8.2.8",
"postcss-loader": "5.2.0",
"postcss-preset-env": "6.7.0",
"prettier": "2.1.2",
"redux-mock-store": "1.5.4",
"rimraf": "3.0.2",
"robotstxt-webpack-plugin": "7.0.0",
"sass-loader": "10.0.2",
"source-map-loader": "1.1.0",
"style-loader": "1.2.1",
"sass-loader": "11.0.1",
"source-map-loader": "2.0.1",
"style-loader": "2.0.0",
"stylelint": "13.7.2",
"stylelint-config-recommended-scss": "4.2.0",
"stylelint-scss": "3.18.0",
"stylelint-webpack-plugin": "2.1.0",
"terser-webpack-plugin": "4.1.0",
"stylelint-webpack-plugin": "2.1.1",
"ts-multipick": "1.0.0",
"typescript": "4.0.3",
"webpack": "4.44.1",
"webpack-bundle-analyzer": "3.8.0",
"webpack-cli": "3.3.12",
"webpack-dev-server": "3.11.0",
"webpack-merge": "5.1.4",
"workbox-webpack-plugin": "5.1.4",
"worker-plugin": "5.0.0"
"webpack": "5.28.0",
"webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2",
"webpack-merge": "5.7.3",
"workbox-webpack-plugin": "6.1.2",
"worker-loader": "3.0.8"
},
"browserslist": [
"> 1% and last 2 versions",
......
module.exports = {
policy: [{ userAgent: '*', disallow: '/' }]
};
......@@ -27,7 +27,8 @@ import {
TranscriptSequenceMetadata
} from './fetchSequenceChecksums';
import {
// @ts-expect-error There is in fact no default export in the worker
import SequenceFetcherWorker, {
WorkerApi,
SingleSequenceFetchParams
} from 'src/shared/workers/sequenceFetcher.worker';
......@@ -50,9 +51,7 @@ export const fetchForProtein = async (payload: FetchPayload) => {
options
});
const worker = new Worker('src/shared/workers/sequenceFetcher.worker', {
type: 'module'
});
const worker = new SequenceFetcherWorker();
const service = wrap<WorkerApi>(worker);
......
......@@ -29,7 +29,8 @@ import {
TranscriptSequenceMetadata
} from './fetchSequenceChecksums';
import {
// @ts-expect-error There is in fact no default export in the worker
import SequenceFetcherWorker, {
WorkerApi,
SingleSequenceFetchParams
} from 'src/shared/workers/sequenceFetcher.worker';
......@@ -74,9 +75,7 @@ export const fetchForTranscript = async (payload: FetchPayload) => {
);
}
const worker = new Worker('src/shared/workers/sequenceFetcher.worker', {
type: 'module'
});
const worker = new SequenceFetcherWorker();
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');
const HtmlPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
const WorkerPlugin = require("worker-plugin");
const { getPaths } = require('../paths');
const { isDevelopment } = require('./environment-detector');
module.exports = (env) => {
const isDev = isDevelopment(env.mode);
const isDev = env.dev;
const paths = getPaths();
return {
// the starting point of webpack bundling
entry: {
......@@ -19,6 +16,13 @@ module.exports = (env) => {
module: {
rules: [
{
test: /\.worker\.ts$/,
use: [
{ loader: "worker-loader" },
{ loader: 'babel-loader' }
],
},
{
test: /.tsx?$/,
loader: 'babel-loader',
......@@ -67,9 +71,9 @@ module.exports = (env) => {
},
// prevent webpack from searching fs (node API) to load the web assembly files
node: {
fs: 'empty'
},
// node: {
// fs: 'empty'
// },
// this is the config to define how the output files needs to be
output: {
......@@ -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
filename: isDev ? 'index.html' : '../index.html',
template: paths.htmlTemplatePath,
publicPath: '/'
}),
new WorkerPlugin()
publicPath: isDev ? '/' : '/static'
})
],
// configuration that allows us to not to use file extensions and shorten import paths (using aliases)
......@@ -109,7 +112,9 @@ module.exports = (env) => {
config: path.join(paths.rootPath, 'config.ts'),
src: path.join(paths.rootPath, 'src'),
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 = {
// concatenate the common config with the dev config
module.exports = () => ({
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devtool: 'eval-cheap-module-source-map',
module: {
rules: [
// this is the loader that will make webpack load file formats that are not supported by other loaders
......
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const BrotliPlugin = require('brotli-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
const RobotstxtPlugin = require('robotstxt-webpack-plugin');
const { getPaths } = require('../paths');
const paths = getPaths('production');
// 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
const dotenv = require('dotenv').config({
......@@ -76,36 +73,35 @@ module.exports = () => {
patterns: [
{
from: path.join(paths.nodeModulesPath, 'ensembl-genome-browser/browser*.wasm'),
to: path.join(paths.buildStaticPath, 'browser'),
flatten: true
to: path.join(paths.buildStaticPath, 'browser', '[name][ext]')
},
{
from: path.join(paths.staticPath, 'favicons/*'),
to: path.join(paths.buildStaticPath, 'favicons'),
flatten: true
to: path.join(paths.buildStaticPath, 'favicons', '[name][ext]')
},
{
from: path.join(paths.staticPath, 'manifest.json'),
to: paths.buildStaticPath,
flatten: true
to: path.join(paths.buildStaticPath, '[name][ext]')
},
{
from: path.join(paths.staticPath, 'robots.txt'),
to: paths.buildPath
}
]
}),
// generate unique hashes for files based on the relative paths
new webpack.HashedModuleIdsPlugin(),
// compress static files 5kB and larger
new CompressionPlugin({
test: /.(js|css|html|wasm)$/,
threshold: 5120,
minRatio: 0.7
}),
// brotli compression for static files
// only files above 5kB will be compressed
new BrotliPlugin({
new CompressionPlugin({
test: /.(js|css|html|wasm)$/,
threshold: 5120, // 5kB
filename: "[path][base].br",
algorithm: "brotliCompress",
threshold: 5120,
minRatio: 0.7
}),
......@@ -114,23 +110,23 @@ module.exports = () => {
swDest: '../service-worker.js', // save service worker in the root folder (/dist) instead of /dist/static
clientsClaim: true,
skipWaiting: true,
exclude: [/index.html$/, /\.gz$/, /\.br$/, /\.js\.map$/]
exclude: [
/index.html$/,
/robots.txt$/,
/\.gz$/,
/\.br$/,
/\.js\.map$/,
/\.css\.map$/,
/^.*favicons\/.*$/ // this is a roundabout way to exclude all files in the favicons folder; simple `/\/favicons\//` regex won't work
]
}),
new RobotstxtPlugin({
filePath: '../robots.txt'
})
],
optimization: {
// use terser plugin instead of uglify js to support minimisation for modern React.js features
// optimize css assets plugin to minimise css as it is not yet supported in webpack by default
// also, optimise/minimise CSS files
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
new TerserPlugin(),
new CssMinimizerPlugin()
],
// create a separate webpack runtime chunk that will be used for all bundles
......@@ -146,7 +142,10 @@ module.exports = () => {
chunks: 'all'
}
}
}
},
// module names are hashed into small numeric values
moduleIds: 'deterministic'
}
}
......
const { merge: webpackMerge } = require('webpack-merge');
/* NOTE:
- env may or may not be passed
- env may or may not contain the presets field
- the presets field contains either a string or an array of strings
*/
const loadPresets = (env) => {
let { presets = [] } = env;
if (typeof presets === 'string') {
presets = [presets];
}
return webpackMerge(presets.map(presetName =>
require(`./webpack.${presetName}`)(env)
));
};
module.exports = loadPresets;
const WebpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = () => ({
plugins: [
new WebpackBundleAnalyzer()
]
})
const { merge: webpackMerge } = require('webpack-merge');
const loadPresets = require('./presets/loadPresets');
const commonConfig = require('./environments/webpack.common.js');
const getConfigForEnvironment = (env = { mode: 'dev' }) =>
require(`./environments/webpack.config.${env.mode}`)(env);
const getConfigForEnvironment = (env = { dev: true }) => {
const mode = env.dev ? 'dev' : 'prod';
return require(`./environments/webpack.config.${mode}`)(env);
}
module.exports = env => {
return webpackMerge(
commonConfig(env),
getConfigForEnvironment(env),
loadPresets(env)
);
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment