Build: Upgrade Webpack 5 (#36444)

* build(webpack): bump to v5 and successful yarn start compilation

* build(webpack): update postcss dependencies

* build(webpack): silence warnings about hash renamed to fullhash

* build(webpack): enable persistent cache to store generated webpack modules / chunks

* build(webpack): prefer eslintWebpackPlugin over tschecker so eslint doesn't block typechecking

* chore(yarn): run yarn-deduplicate to clean up dependencies

* chore(yarn): refresh lock file after clean install

* build(webpack): prefer output.clean over CleanWebpackPlugin

* build(webpack): prefer esbuild over babel-loader for dev config

* build(babel): turn off cache compression to improve build performance

* build(webpack): get production builds working

* build(webpack): remove phantomJS (removed from grafana in v7) specific loader

* build(webpack): put back babel for dev builds no performance gain in using esbuild in webpack

* build(webpack): prefer terser and optimise css plugins for prod. slower but smaller bundles

* build(webpack): clean up redundant code. inform postcss about node_modules

* build(webpack): remove deprecation warnings flag

* build(webpack): bump packages, dev performance optimisations, attempt to get hot working

* chore(storybook): use webpack 5 for dev and production builds

* build(storybook): speed up dev build

* chore(yarn): refresh lock file

* chore(webpack): bump webpack and related deps to latest

* refactor(webpack): put back inline-source-map, move start scripts out of grafana toolkit

* feat(webpack): prefer react-refresh over react-hot-loader

* build(webpack): update webpack.hot to use react-refresh

* chore: remove react-hot-loader from codebase

* refactor(queryeditorrow): fix circular dependency causing react-fast-refresh errors

* revert(webpack): remove stats.errorDetails from common config

* build(webpack): bump to v5 and successful yarn start compilation

* build(webpack): update postcss dependencies

* build(webpack): silence warnings about hash renamed to fullhash

* build(webpack): enable persistent cache to store generated webpack modules / chunks

* build(webpack): prefer eslintWebpackPlugin over tschecker so eslint doesn't block typechecking

* chore(yarn): run yarn-deduplicate to clean up dependencies

* chore(yarn): refresh lock file after clean install

* build(webpack): prefer output.clean over CleanWebpackPlugin

* build(webpack): prefer esbuild over babel-loader for dev config

* build(babel): turn off cache compression to improve build performance

* build(webpack): get production builds working

* build(webpack): remove phantomJS (removed from grafana in v7) specific loader

* build(webpack): put back babel for dev builds no performance gain in using esbuild in webpack

* build(webpack): prefer terser and optimise css plugins for prod. slower but smaller bundles

* build(webpack): clean up redundant code. inform postcss about node_modules

* build(webpack): remove deprecation warnings flag

* build(webpack): bump packages, dev performance optimisations, attempt to get hot working

* chore(storybook): use webpack 5 for dev and production builds

* build(storybook): speed up dev build

* chore(yarn): refresh lock file

* chore(webpack): bump webpack and related deps to latest

* refactor(webpack): put back inline-source-map, move start scripts out of grafana toolkit

* feat(webpack): prefer react-refresh over react-hot-loader

* build(webpack): update webpack.hot to use react-refresh

* chore: remove react-hot-loader from codebase

* refactor(queryeditorrow): fix circular dependency causing react-fast-refresh errors

* revert(webpack): remove stats.errorDetails from common config

* revert(webpack): remove include from babel-loader so symlinks (enterprise) work as before

* refactor(webpack): fix deprecation warnings in prod builds

* fix(storybook): fix failing builds due to replacing css-optimise webpack plugin

* fix(storybook): use raw-loader for svg icons

* build(webpack): fix dev script colors error

* chore(webpack): bump css-loader and react-refresh-webpack-plugin to latest versions

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
Jack Westbrook
2021-08-31 12:55:05 +02:00
committed by GitHub
co-authored by Torkel Ödegaard
parent b40d48258d
commit 8d3b31ff23
47 changed files with 1947 additions and 1147 deletions
+8 -1
View File
@@ -1,6 +1,7 @@
module.exports = function getBabelConfig(options = {}) {
return {
const babelOptions = {
cacheDirectory: true,
cacheCompression: false,
babelrc: false,
// Note: order is bottom-to-top and/or right-to-left
presets: [
@@ -43,4 +44,10 @@ module.exports = function getBabelConfig(options = {}) {
'angularjs-annotate',
],
};
if (options.REACT_REFRESH) {
babelOptions.plugins.push('react-refresh/babel');
}
return babelOptions;
};
+1 -1
View File
@@ -83,7 +83,7 @@ module.exports.pitch = function pitch(remainingRequest) {
function getOutputFilename(options, { target }) {
if (!options) {
return { filename: `[hash].${target}.js`, options: undefined };
return { filename: `[fullhash].${target}.js`, options: undefined };
}
if (typeof options === 'string') {
return { filename: options, options: undefined };
+6 -8
View File
@@ -1,9 +1,7 @@
module.exports = () => {
return {
plugins: {
autoprefixer: {},
'postcss-reporter': {},
'postcss-browser-reporter': {},
},
};
module.exports = {
plugins: {
autoprefixer: {},
'postcss-reporter': {},
'postcss-browser-reporter': {},
},
};
+5 -1
View File
@@ -1,10 +1,12 @@
'use strict';
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = function (options) {
return {
test: /\.scss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
@@ -19,7 +21,9 @@ module.exports = function (options) {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap,
config: { path: __dirname },
postcssOptions: {
config: path.resolve(__dirname),
},
},
},
{
+18 -54
View File
@@ -2,7 +2,6 @@ const fs = require('fs-extra');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const getBabelConfig = require('./babel.config');
class CopyUniconsPlugin {
apply(compiler) {
@@ -17,31 +16,15 @@ class CopyUniconsPlugin {
}
}
// https://github.com/visionmedia/debug/issues/701#issuecomment-505487361
function shouldExclude(filename) {
// There is external js code inside this which needs to be processed by babel.
if (filename.indexOf(`jaeger-ui-components`) > 0) {
return false;
}
const packagesToProcessbyBabel = ['debug', 'lru-cache', 'yallist', 'react-hook-form', 'rc-trigger'];
for (const package of packagesToProcessbyBabel) {
if (filename.indexOf(`node_modules/${package}`) > 0) {
return false;
}
}
return true;
}
console.log(path.resolve());
module.exports = {
target: 'web',
entry: {
app: './public/app/index.ts',
},
output: {
clean: true,
path: path.resolve(__dirname, '../../public/build'),
filename: '[name].[hash].js',
filename: '[name].[fullhash].js',
// Keep publicPath relative for host.com/grafana/ deployments
publicPath: 'public/build/',
},
@@ -64,15 +47,16 @@ module.exports = {
// we need full path to root node_modules for grafana-enterprise symlink to work
path.resolve('node_modules'),
],
fallback: {
fs: false,
stream: false,
},
},
ignoreWarnings: [/export .* was not found in/],
stats: {
children: false,
warningsFilter: /export .* was not found in/,
source: false,
},
node: {
fs: 'empty',
},
plugins: [
new CopyUniconsPlugin(),
new CopyWebpackPlugin({
@@ -97,33 +81,12 @@ module.exports = {
],
module: {
rules: [
/**
* Some npm packages are bundled with es2015 syntax, ie. debug
* To make them work with PhantomJS we need to transpile them
* to get rid of unsupported syntax.
*/
{
test: /\.js$/,
exclude: shouldExclude,
use: [
{
loader: 'babel-loader',
options: getBabelConfig(),
},
],
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
query: 'jQuery',
},
{
loader: 'expose-loader',
query: '$',
},
],
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
},
{
test: /\.html$/,
@@ -135,10 +98,11 @@ module.exports = {
{
loader: 'html-loader',
options: {
attrs: [],
minimize: true,
removeComments: false,
collapseWhitespace: false,
sources: false,
minimize: {
removeComments: false,
collapseWhitespace: false,
},
},
},
],
@@ -170,7 +134,7 @@ module.exports = {
},
// https://webpack.js.org/plugins/split-chunks-plugin/#split-chunks-example-3
optimization: {
moduleIds: 'hashed',
moduleIds: 'named',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
@@ -194,7 +158,7 @@ module.exports = {
priority: 50,
enforce: true,
},
vendors: {
defaultVendors: {
test: /[\\/]node_modules[\\/].*[jt]sx?$/,
chunks: 'initial',
priority: -10,
+32 -24
View File
@@ -1,11 +1,11 @@
'use strict';
const merge = require('webpack-merge');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
const webpack = require('webpack');
const { DefinePlugin } = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const getBabelConfig = require('./babel.config');
@@ -32,13 +32,11 @@ module.exports = (env = {}) =>
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'babel-loader',
options: getBabelConfig({ BABEL_ENV: 'dev' }),
},
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: getBabelConfig({ BABEL_ENV: 'dev' }),
},
],
},
require('./sass.rule.js')({
sourceMap: false,
@@ -47,19 +45,25 @@ module.exports = (env = {}) =>
],
},
// https://webpack.js.org/guides/build-performance/#output-without-path-info
output: {
pathinfo: false,
filename: '[name].js',
},
// https://webpack.js.org/guides/build-performance/#avoid-extra-optimization-steps
optimization: {
runtimeChunk: true,
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
plugins: [
new CleanWebpackPlugin(),
env.noTsCheck
? new webpack.DefinePlugin({}) // bogus plugin to satisfy webpack API
parseInt(env.noTsCheck, 10)
? new DefinePlugin({}) // bogus plugin to satisfy webpack API
: new ForkTsCheckerWebpackPlugin({
eslint: {
enabled: true,
files: ['public/app/**/*.{ts,tsx}', 'packages/*/src/**/*.{ts,tsx}'],
options: {
cache: true,
},
memoryLimit: 4096,
},
async: true, // don't block webpack emit
typescript: {
mode: 'write-references',
memoryLimit: 4096,
@@ -69,8 +73,13 @@ module.exports = (env = {}) =>
},
},
}),
// next major version of ForkTsChecker is dropping support for ESLint
new ESLintPlugin({
lintDirtyModulesOnly: true, // don't lint on start, only lint changed files
extensions: ['.ts', '.tsx'],
}),
new MiniCssExtractPlugin({
filename: 'grafana.[name].[hash].css',
filename: 'grafana.[name].[fullhash].css',
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/error.html'),
@@ -82,13 +91,12 @@ module.exports = (env = {}) =>
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/index.html'),
template: path.resolve(__dirname, '../../public/views/index-template.html'),
hash: true,
inject: false,
chunksSortMode: 'none',
excludeChunks: ['dark', 'light'],
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
new DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
+49 -62
View File
@@ -1,104 +1,91 @@
'use strict';
const merge = require('webpack-merge');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
const webpack = require('webpack');
const { DefinePlugin } = require('webpack');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const getBabelConfig = require('./babel.config');
module.exports = merge(common, {
devtool: 'inline-source-map',
mode: 'development',
entry: {
app: ['webpack-dev-server/client?http://localhost:3333', './public/app/dev.ts'],
app: ['./public/app/index.ts'],
dark: './public/sass/grafana.dark.scss',
light: './public/sass/grafana.light.scss',
},
output: {
path: path.resolve(__dirname, '../../public/build'),
filename: '[name].[hash].js',
publicPath: '/public/build/',
pathinfo: false,
watchOptions: {
ignored: /node_modules/,
},
resolve: {
extensions: ['.scss', '.ts', '.tsx', '.es6', '.js', '.json', '.svg', '.woff2', '.png', '.html'],
},
devtool: 'eval-source-map',
devServer: {
publicPath: '/public/build/',
devMiddleware: {
writeToDisk: true,
},
historyApiFallback: true,
hot: true,
open: false,
port: 3333,
proxy: {
'!/public/build': 'http://localhost:3000',
},
watchOptions: {
ignored: /node_modules/,
static: {
publicPath: '/public/build/',
},
},
optimization: {
removeAvailableModules: false,
runtimeChunk: false,
removeEmptyChunks: false,
splitChunks: false,
},
module: {
// Note: order is bottom-to-top and/or right-to-left
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'babel-loader',
options: getBabelConfig({ BABEL_ENV: 'dev', REACT_REFRESH: true }),
},
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: getBabelConfig(),
},
],
},
{
test: /\.scss$/,
use: [
'style-loader', // creates style nodes from JS strings
'css-loader', // translates CSS into CommonJS
{
loader: 'postcss-loader',
options: {
config: {
path: __dirname + '/postcss.config.js',
},
},
},
{
loader: 'sass-loader',
},
],
},
{
test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: 'file-loader',
include: [path.resolve(__dirname, '../../public/'), path.resolve(__dirname, '../../packages/')],
},
require('./sass.rule.js')({
sourceMap: false,
preserveUrl: false,
}),
],
},
// https://webpack.js.org/guides/build-performance/#output-without-path-info
output: {
filename: '[name].js',
pathinfo: false,
},
// https://webpack.js.org/guides/build-performance/#avoid-extra-optimization-steps
optimization: {
runtimeChunk: true,
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'grafana.[name].[fullhash].css',
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/index.html'),
template: path.resolve(__dirname, '../../public/views/index-template.html'),
inject: 'body',
alwaysWriteToDisk: true,
hash: true,
inject: false,
chunksSortMode: 'none',
excludeChunks: ['dark', 'light'],
}),
new HtmlWebpackHarddiskPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
GRAFANA_THEME: JSON.stringify(process.env.GRAFANA_THEME || 'dark'),
new ReactRefreshWebpackPlugin(),
new DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
+4 -6
View File
@@ -1,12 +1,12 @@
'use strict';
const merge = require('webpack-merge');
const { merge } = require('webpack-merge');
const TerserPlugin = require('terser-webpack-plugin');
const common = require('./webpack.common.js');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const getBabelConfig = require('./babel.config');
module.exports = merge(common, {
@@ -41,16 +41,14 @@ module.exports = merge(common, {
nodeEnv: 'production',
minimizer: [
new TerserPlugin({
cache: false,
parallel: false,
sourceMap: true,
}),
new OptimizeCSSAssetsPlugin({}),
new CssMinimizerPlugin(),
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'grafana.[name].[hash].css',
filename: 'grafana.[name].[fullhash].css',
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/error.html'),