Performance/Webpack: Introduces more aggressive code-splitting and other perf improvements (#18544)
* Performance/Webpack: Introduces more aggressive code-splitting and other perf improvements - Introduces dynamic imports for built-in plugins - Uses dynamic imports for various packages (rst2html, brace) - Introduces route-based dynamic imports - Splits angular and moment into separate bundles
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const pkg = require('../../package.json');
|
||||
const _ = require('lodash');
|
||||
const pull = require('lodash/pull');
|
||||
|
||||
let dependencies = Object.keys(pkg.dependencies);
|
||||
// remove jquery so we can add it first
|
||||
// remove rxjs so we can only depend on parts of it in code
|
||||
_.pull(dependencies, 'jquery', 'rxjs')
|
||||
pull(dependencies, 'jquery', 'rxjs')
|
||||
|
||||
// add jquery first
|
||||
dependencies.unshift('jquery');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const path = require('path');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
target: 'web',
|
||||
@@ -13,63 +14,88 @@ module.exports = {
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.es6', '.js', '.json', '.svg'],
|
||||
alias: {
|
||||
},
|
||||
modules: [
|
||||
path.resolve('public'),
|
||||
path.resolve('node_modules')
|
||||
],
|
||||
alias: {},
|
||||
modules: [path.resolve('public'), path.resolve('node_modules')],
|
||||
},
|
||||
stats: {
|
||||
children: false,
|
||||
warningsFilter: /export .* was not found in/
|
||||
warningsFilter: /export .* was not found in/,
|
||||
source: false
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
rules: [{
|
||||
test: require.resolve('jquery'),
|
||||
use: [
|
||||
{
|
||||
use: [{
|
||||
loader: 'expose-loader',
|
||||
query: 'jQuery'
|
||||
query: 'jQuery',
|
||||
},
|
||||
{
|
||||
loader: 'expose-loader',
|
||||
query: '$'
|
||||
}
|
||||
]
|
||||
query: '$',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
exclude: /(index|error)\-template\.html/,
|
||||
use: [
|
||||
{ loader: 'ngtemplate-loader?relativeTo=' + (path.resolve(__dirname, '../../public')) + '&prefix=public' },
|
||||
use: [{
|
||||
loader: 'ngtemplate-loader?relativeTo=' + path.resolve(__dirname, '../../public') + '&prefix=public',
|
||||
},
|
||||
{
|
||||
loader: 'html-loader',
|
||||
options: {
|
||||
attrs: [],
|
||||
minimize: true,
|
||||
removeComments: false,
|
||||
collapseWhitespace: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
collapseWhitespace: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// https://webpack.js.org/plugins/split-chunks-plugin/#split-chunks-example-3
|
||||
optimization: {
|
||||
moduleIds: 'hashed',
|
||||
runtimeChunk: 'single',
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
minChunks: 1,
|
||||
cacheGroups: {
|
||||
commons: {
|
||||
moment: {
|
||||
test: /[\\/]node_modules[\\/]moment[\\/].*[jt]sx?$/,
|
||||
chunks: 'initial',
|
||||
priority: 20,
|
||||
enforce: true
|
||||
},
|
||||
angular: {
|
||||
test: /[\\/]node_modules[\\/]angular[\\/].*[jt]sx?$/,
|
||||
chunks: 'initial',
|
||||
priority: 50,
|
||||
enforce: true
|
||||
},
|
||||
vendors: {
|
||||
test: /[\\/]node_modules[\\/].*[jt]sx?$/,
|
||||
name: 'vendor',
|
||||
chunks: 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
chunks: 'initial',
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
enforce: true
|
||||
},
|
||||
default: {
|
||||
priority: -20,
|
||||
chunks: 'all',
|
||||
test: /.*[jt]sx?$/,
|
||||
reuseExistingChunk: true
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
checkSyntacticErrors: true,
|
||||
})
|
||||
],
|
||||
};
|
||||
|
||||
@@ -27,8 +27,7 @@ module.exports = (env = {}) =>
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
rules: [{
|
||||
test: /\.tsx?$/,
|
||||
enforce: 'pre',
|
||||
exclude: /node_modules/,
|
||||
@@ -37,8 +36,8 @@ module.exports = (env = {}) =>
|
||||
options: {
|
||||
emitErrors: true,
|
||||
typeCheck: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
@@ -46,48 +45,55 @@ module.exports = (env = {}) =>
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
transpileOnly: true
|
||||
},
|
||||
},
|
||||
},
|
||||
require('./sass.rule.js')({ sourceMap: false, preserveUrl: false }),
|
||||
require('./sass.rule.js')({
|
||||
sourceMap: false,
|
||||
preserveUrl: false
|
||||
}),
|
||||
{
|
||||
test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
|
||||
loader: 'file-loader',
|
||||
loader: 'file-loader'
|
||||
},
|
||||
],
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
env.noTsCheck
|
||||
? new webpack.DefinePlugin({}) // bogus plugin to satisfy webpack API
|
||||
: new ForkTsCheckerWebpackPlugin({
|
||||
checkSyntacticErrors: true,
|
||||
}),
|
||||
env.noTsCheck ?
|
||||
new webpack.DefinePlugin({}) // bogus plugin to satisfy webpack API
|
||||
:
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
checkSyntacticErrors: true,
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'grafana.[name].[hash].css',
|
||||
filename: "grafana.[name].[hash].css"
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/error.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/error-template.html'),
|
||||
inject: false,
|
||||
chunksSortMode: 'none',
|
||||
excludeChunks: ['dark', 'light']
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
chunks: ['manifest', 'vendor', 'app'],
|
||||
chunksSortMode: 'none',
|
||||
excludeChunks: ['dark', 'light']
|
||||
}),
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify('development'),
|
||||
},
|
||||
'NODE_ENV': JSON.stringify('development')
|
||||
}
|
||||
}),
|
||||
// new BundleAnalyzerPlugin({
|
||||
// analyzerPort: 8889
|
||||
// })
|
||||
],
|
||||
]
|
||||
});
|
||||
|
||||
@@ -42,41 +42,44 @@ module.exports = merge(common, {
|
||||
|
||||
optimization: {
|
||||
removeAvailableModules: false,
|
||||
runtimeChunk: false,
|
||||
removeEmptyChunks: false,
|
||||
splitChunks: false,
|
||||
splitChunks: false
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
rules: [{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
babelrc: false,
|
||||
plugins: [
|
||||
[require('@rtsao/plugin-proposal-class-properties'), { loose: true }],
|
||||
'angularjs-annotate',
|
||||
'@babel/plugin-syntax-dynamic-import', // needed for `() => import()` in routes.ts
|
||||
'react-hot-loader/babel',
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: { browsers: 'last 3 versions' },
|
||||
useBuiltIns: 'entry',
|
||||
use: [{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
babelrc: false,
|
||||
plugins: [
|
||||
[require('@rtsao/plugin-proposal-class-properties'), {
|
||||
loose: true
|
||||
}],
|
||||
'angularjs-annotate',
|
||||
'@babel/plugin-syntax-dynamic-import', // needed for `() => import()` in routes.ts
|
||||
'react-hot-loader/babel',
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
browsers: 'last 3 versions'
|
||||
},
|
||||
],
|
||||
'@babel/preset-typescript',
|
||||
'@babel/preset-react',
|
||||
useBuiltIns: 'entry',
|
||||
modules: false
|
||||
},
|
||||
],
|
||||
},
|
||||
'@babel/preset-typescript',
|
||||
'@babel/preset-react',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, ],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
@@ -86,7 +89,9 @@ module.exports = merge(common, {
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: { path: __dirname + '/postcss.config.js' },
|
||||
config: {
|
||||
path: __dirname + '/postcss.config.js'
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -108,6 +113,7 @@ module.exports = merge(common, {
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
alwaysWriteToDisk: true,
|
||||
chunksSortMode: 'none'
|
||||
}),
|
||||
new HtmlWebpackHarddiskPlugin(),
|
||||
new webpack.NamedModulesPlugin(),
|
||||
|
||||
@@ -20,8 +20,7 @@ module.exports = merge(common, {
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
rules: [{
|
||||
test: /\.tsx?$/,
|
||||
enforce: 'pre',
|
||||
exclude: /node_modules/,
|
||||
@@ -44,11 +43,13 @@ module.exports = merge(common, {
|
||||
},
|
||||
},
|
||||
require('./sass.rule.js')({
|
||||
sourceMap: false, preserveUrl: false
|
||||
sourceMap: false,
|
||||
preserveUrl: false
|
||||
})
|
||||
]
|
||||
},
|
||||
optimization: {
|
||||
nodeEnv: 'production',
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
cache: false,
|
||||
@@ -70,12 +71,15 @@ module.exports = merge(common, {
|
||||
filename: path.resolve(__dirname, '../../public/views/error.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/error-template.html'),
|
||||
inject: false,
|
||||
excludeChunks: ['dark', 'light'],
|
||||
chunksSortMode: 'none'
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
chunks: ['vendor', 'app'],
|
||||
excludeChunks: ['manifest', 'dark', 'light'],
|
||||
chunksSortMode: 'none'
|
||||
}),
|
||||
function () {
|
||||
this.hooks.done.tap('Done', function (stats) {
|
||||
|
||||
Reference in New Issue
Block a user