Merge pull request #12882 from strapi/enhancement/speed-up-webpack

Enhancement/speed up webpack
This commit is contained in:
cyril lopez 2022-03-24 14:29:24 +01:00 committed by GitHub
commit 2627aa6ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 159 additions and 95 deletions

View File

@ -1,7 +1,7 @@
{
"name": "getstarted",
"private": true,
"version": "4.2.0-beta.0",
"version": "4.1.4",
"description": "A Strapi application.",
"scripts": {
"develop": "strapi develop",

View File

@ -28,6 +28,7 @@
"develop:webpack": "cross-env NODE_ENV=development webpack serve --config webpack.config.dev.js --progress profile",
"prepublishOnly": "yarn build",
"build": "rimraf build && node ./scripts/build.js",
"build:mesure": "rimraf build && cross-env MESURE_BUILD_SPEED=true node ./scripts/build.js",
"test": "echo \"no tests yet\"",
"test:unit": "jest --verbose",
"test:front": "cross-env IS_EE=true jest --config ./jest.config.front.js",
@ -37,10 +38,6 @@
},
"dependencies": {
"@babel/core": "7.16.7",
"@babel/plugin-proposal-async-generator-functions": "7.16.7",
"@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.16.7",
"@babel/plugin-transform-runtime": "7.16.7",
"@babel/preset-env": "7.16.7",
"@babel/preset-react": "7.16.7",
@ -131,7 +128,6 @@
"sift": "13.5.0",
"style-loader": "3.3.1",
"styled-components": "^5.2.3",
"terser-webpack-plugin": "5.3.0",
"webpack": "5.65.0",
"webpack-cli": "4.9.1",
"webpack-dev-server": "4.7.3",
@ -140,6 +136,7 @@
},
"devDependencies": {
"duplicate-dependencies-webpack-plugin": "0.2.0",
"speed-measure-webpack-plugin": "1.5.0",
"webpack-bundle-analyzer": "4.4.1"
},
"engines": {

View File

@ -2,7 +2,10 @@
const path = require('path');
const webpack = require('webpack');
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const webpackConfig = require('../webpack.config');
const getPluginsPath = require('../utils/get-plugins-path');
const {
getCorePluginsPath,
getPluginToInstallPath,
@ -11,20 +14,24 @@ const {
const PLUGINS_TO_INSTALL = ['i18n', 'users-permissions'];
// Wrapper that outputs the webpack speed
const smp = new SpeedMeasurePlugin();
const buildAdmin = async () => {
const entry = path.join(__dirname, '..', 'admin', 'src');
const dest = path.join(__dirname, '..', 'build');
const corePlugins = getCorePluginsPath();
const plugins = getPluginToInstallPath(PLUGINS_TO_INSTALL);
const allPlugins = { ...corePlugins, ...plugins };
const pluginsPath = getPluginsPath();
await createPluginsFile(allPlugins);
const args = {
entry,
dest,
cacheDir: __dirname,
pluginsPath: [path.resolve(__dirname, '../../../../packages')],
cacheDir: path.join(__dirname, '..'),
pluginsPath,
env: 'production',
optimize: true,
options: {
@ -33,7 +40,10 @@ const buildAdmin = async () => {
},
};
const compiler = webpack(webpackConfig(args));
const config =
process.env.MESURE_BUILD_SPEED === 'true' ? smp.wrap(webpackConfig(args)) : webpackConfig(args);
const compiler = webpack(config);
console.log('Building the admin panel');
@ -73,7 +83,7 @@ buildAdmin()
.then(() => {
process.exit();
})
.catch(err => {
.catch((err) => {
console.error(err);
process.exit(1);
});

View File

@ -0,0 +1,23 @@
'use strict';
const getPluginsPath = require('../get-plugins-path');
describe('getPluginsPath', () => {
test('should return an array of directories that contains an admin/src/index.js file', () => {
const results = getPluginsPath();
expect(results.length).toBeGreaterThan(0);
// Test that the content-type-builder is included
expect(results.findIndex(p => p.includes('/core/content-type-builder/admin'))).not.toEqual(-1);
// Test that the upload is included
expect(results.findIndex(p => p.includes('/core/upload/admin'))).not.toEqual(-1);
// Test that the documentation is included
expect(results.findIndex(p => p.includes('/plugins/documentation/admin'))).not.toEqual(-1);
// Test that the CM is not included
expect(results.findIndex(p => p.includes('/core/content-manager/admin'))).toEqual(-1);
// Test that the admin package is not included
expect(results.findIndex(p => p.includes('/core/admin/admin'))).toEqual(-1);
// Test that the helper-plugin package is not included
expect(results.findIndex(p => p.includes('helper-plugin'))).toEqual(-1);
});
});

View File

@ -0,0 +1,26 @@
'use strict';
const { join, resolve } = require('path');
const fs = require('fs-extra');
// eslint-disable-next-line node/no-extraneous-require
const glob = require('glob');
const getPluginsPath = () => {
const rootPath = resolve(__dirname, '..', join('..', '..', '..', 'packages'));
const corePath = join(rootPath, 'core', '*');
const pluginsPath = join(rootPath, 'plugins', '*');
const corePackageDirs = glob.sync(corePath);
const pluginsPackageDirs = glob.sync(pluginsPath);
const packageDirs = [...corePackageDirs, ...pluginsPackageDirs].filter(dir => {
const isCoreAdmin = dir.includes('packages/core/admin');
const pathToEntryPoint = join(dir, 'admin', 'src', 'index.js');
const doesAdminFolderExist = fs.pathExistsSync(pathToEntryPoint);
return !isCoreAdmin && doesAdminFolderExist;
});
return packageDirs.map(dir => resolve(__dirname, '..', join(dir, 'admin', 'src')));
};
module.exports = getPluginsPath;

View File

@ -3,7 +3,7 @@
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const { DuplicateReporterPlugin } = require('duplicate-dependencies-webpack-plugin');
const getPluginsPath = require('./utils/get-plugins-path');
const webpackConfig = require('./webpack.config');
module.exports = () => {
@ -19,11 +19,12 @@ module.exports = () => {
backend: 'http://localhost:1337',
adminPath: '/admin/',
};
const pluginsPath = getPluginsPath();
const args = {
entry,
cacheDir: __dirname,
pluginsPath: [path.resolve(__dirname, '../../../packages')],
pluginsPath,
dest,
env,
options,
@ -41,27 +42,6 @@ module.exports = () => {
return {
...config,
snapshot: {
managedPaths: [
path.resolve(__dirname, '../content-type-builder'),
path.resolve(__dirname, '../upload'),
path.resolve(__dirname, '../helper-plugin'),
],
buildDependencies: {
hash: true,
timestamp: true,
},
module: {
timestamp: true,
},
resolve: {
timestamp: true,
},
resolveBuildDependencies: {
hash: true,
timestamp: true,
},
},
devServer: {
port: 4000,

View File

@ -1,14 +1,14 @@
'use strict';
const path = require('path');
const fse = require('fs-extra');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { ESBuildMinifyPlugin } = require('esbuild-loader');
const WebpackBar = require('webpackbar');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const isWsl = require('is-wsl');
const alias = require('./webpack.alias');
const getClientEnvironment = require('./env');
@ -79,6 +79,11 @@ module.exports = ({
});
}
// Directly inject a polyfill in the webpack entry point before the entry point
// FIXME: I have noticed a bug regarding the helper-plugin and esbuild-loader
// The only I could fix it was to inject the babel polyfill
const babelPolyfill = '@babel/polyfill/dist/polyfill.min.js';
return {
mode: isProduction ? 'production' : 'development',
bail: isProduction ? true : false,
@ -86,7 +91,7 @@ module.exports = ({
experiments: {
topLevelAwait: true,
},
entry,
entry: [babelPolyfill, entry],
output: {
path: dest,
publicPath: options.adminPath,
@ -98,28 +103,9 @@ module.exports = ({
optimization: {
minimize: optimize,
minimizer: [
// Copied from react-scripts
new TerserPlugin({
terserOptions: {
parse: {
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
comparisons: false,
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
},
parallel: !isWsl,
new ESBuildMinifyPlugin({
target: 'es2015',
css: true, // Apply minification to CSS assets
}),
],
runtimeChunk: true,
@ -128,8 +114,28 @@ module.exports = ({
rules: [
{
test: /\.m?js$/,
// TODO remove when plugins are built separately
include: [cacheDir, ...pluginsPath],
include: cacheDir,
oneOf: [
// Use babel-loader for files that distinct the ee and ce code
// These files have an import Something from 'ee_else_ce/
{
test(filePath) {
if (!filePath) {
return false;
}
try {
const fileContent = fse.readFileSync(filePath).toString();
if (fileContent.match(/from.* ['"]ee_else_ce\//)) {
return true;
}
return false;
} catch (e) {
return false;
}
},
use: {
loader: require.resolve('babel-loader'),
options: {
@ -148,15 +154,10 @@ module.exports = ({
roots,
},
],
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-syntax-dynamic-import'),
require.resolve('@babel/plugin-transform-modules-commonjs'),
require.resolve('@babel/plugin-proposal-async-generator-functions'),
[
require.resolve('@babel/plugin-transform-runtime'),
{
// absoluteRuntime: true,s
helpers: true,
regenerator: true,
},
@ -166,6 +167,29 @@ module.exports = ({
},
},
},
// Use esbuild-loader for the other files
{
use: {
loader: require.resolve('esbuild-loader'),
options: {
loader: 'jsx',
target: 'es2015',
},
},
},
],
},
{
test: /\.m?js$/,
include: pluginsPath,
use: {
loader: require.resolve('esbuild-loader'),
options: {
loader: 'jsx',
target: 'es2015',
},
},
},
{
test: /\.css$/i,
@ -212,8 +236,6 @@ module.exports = ({
new HtmlWebpackPlugin({
inject: true,
template: path.resolve(__dirname, 'index.html'),
// FIXME
// favicon: path.resolve(__dirname, 'admin/src/favicon.ico'),
}),
new webpack.DefinePlugin(envVariables),

View File

@ -21,7 +21,6 @@
}
],
"main": "build/index.js",
"module": "lib/src/index.js",
"files": [
"build"
],

View File

@ -20922,6 +20922,13 @@ specificity@^0.4.1:
resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019"
integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==
speed-measure-webpack-plugin@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.5.0.tgz#caf2c5bee24ab66c1c7c30e8daa7910497f7681a"
integrity sha512-Re0wX5CtM6gW7bZA64ONOfEPEhwbiSF/vz6e2GvadjuaPrQcHTQdRGsD8+BE7iUOysXH8tIenkPCQBEcspXsNg==
dependencies:
chalk "^4.1.0"
split-array-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/split-array-stream/-/split-array-stream-2.0.0.tgz#85a4f8bfe14421d7bca7f33a6d176d0c076a53b1"