Skip to content

Commit 142a4ea

Browse files
committed
perf: 优化构建
1 parent 863e48d commit 142a4ea

File tree

19 files changed

+539
-402
lines changed

19 files changed

+539
-402
lines changed

.babelrc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
{
22
"presets": ["react-app"],
33
"plugins": [
4-
[
5-
"@babel/plugin-proposal-decorators",
6-
{
7-
"legacy": true
8-
}
9-
],
104
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
115
]
126
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.formatOnSave": false // 每次保存的时候自动格式化
3+
}

config/webpack.config.js

Lines changed: 104 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@ const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin')
2525
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin')
2626
const typescriptFormatter = require('react-dev-utils/typescriptFormatter')
2727
const CompressionPlugin = require('compression-webpack-plugin')
28+
29+
// ==== plugins
2830
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
31+
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
32+
const os = require('os')
33+
const HappyPack = require('happypack')
34+
// 手动创建进程池
35+
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
36+
// ==== plugins end
2937

3038
const postcssNormalize = require('postcss-normalize')
3139

@@ -43,10 +51,12 @@ const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '10
4351
const useTypeScript = fs.existsSync(paths.appTsConfig)
4452

4553
// style files regexes
46-
const cssRegex = /\.(css|less)$/
54+
const cssRegex = /\.css$/
4755
const cssModuleRegex = /\.module\.css$/
4856
const sassRegex = /\.(scss|sass)$/
4957
const sassModuleRegex = /\.module\.(scss|sass)$/
58+
const lessRegex = /\.less$/;
59+
const lessModuleRegex = /\.module\.less$/;
5060

5161
// This is the production and development configuration.
5262
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
@@ -105,10 +115,6 @@ module.exports = function(webpackEnv) {
105115
],
106116
sourceMap: isEnvProduction && shouldUseSourceMap
107117
}
108-
},
109-
{
110-
loader: require.resolve('less-loader'),
111-
options: cssOptions
112118
}
113119
].filter(Boolean)
114120
if (preProcessor) {
@@ -184,6 +190,9 @@ module.exports = function(webpackEnv) {
184190
// are used on the same page.
185191
jsonpFunction: `webpackJsonp${appPackageJson.name}`
186192
},
193+
externals: {
194+
'highlight.js': 'hljs'
195+
},
187196
optimization: {
188197
minimize: isEnvProduction,
189198
minimizer: [
@@ -261,19 +270,18 @@ module.exports = function(webpackEnv) {
261270
chunks: 'initial',
262271
minChunks: 2
263272
},
264-
'react-vendor': {
265-
test: /[\\/]node_modules[\\/](react|react-dom|redux|react-router-dom)[\\/]/,
266-
name: 'react-vendor',
267-
priority: 3,
268-
reuseExistingChunk: false
269-
},
273+
// 'react-vendor': {
274+
// test: /[\\/]node_modules[\\/](react|react-dom|redux|react-router-dom)[\\/]/,
275+
// name: 'react-vendor',
276+
// priority: 3,
277+
// reuseExistingChunk: false
278+
// },
270279
'antd-vendor': {
271280
test: /[\\/]node_modules[\\/](antd)[\\/]/,
272281
name: 'antd-vendor',
273282
priority: 2,
274283
reuseExistingChunk: false
275284
},
276-
277285
}
278286
},
279287
// Keep the runtime chunk separated to enable long term caching
@@ -362,50 +370,14 @@ module.exports = function(webpackEnv) {
362370
{
363371
test: /\.(js|mjs|jsx|ts|tsx)$/,
364372
include: paths.appSrc,
365-
loader: require.resolve('babel-loader'),
366-
options: {
367-
customize: require.resolve('babel-preset-react-app/webpack-overrides'),
368-
369-
plugins: [
370-
[
371-
require.resolve('babel-plugin-named-asset-import'),
372-
{
373-
loaderMap: {
374-
svg: {
375-
ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]'
376-
}
377-
}
378-
}
379-
]
380-
],
381-
// This is a feature of `babel-loader` for webpack (not Babel itself).
382-
// It enables caching results in ./node_modules/.cache/babel-loader/
383-
// directory for faster rebuilds.
384-
cacheDirectory: true,
385-
cacheCompression: isEnvProduction,
386-
compact: isEnvProduction
387-
}
373+
loader: 'happypack/loader?id=babelInside'
388374
},
389375
// Process any JS outside of the app with Babel.
390376
// Unlike the application JS, we only compile the standard ES features.
391377
{
392378
test: /\.(js|mjs)$/,
393379
exclude: /@babel(?:\/|\\{1,2})runtime/,
394-
loader: require.resolve('babel-loader'),
395-
options: {
396-
babelrc: false,
397-
configFile: false,
398-
compact: false,
399-
presets: [[require.resolve('babel-preset-react-app/dependencies'), { helpers: true }]],
400-
cacheDirectory: true,
401-
cacheCompression: isEnvProduction,
402-
403-
// If an error happens in a package, it's possible to be
404-
// because it was compiled. Thus, we don't want the browser
405-
// debugger to show the original code. Instead, the code
406-
// being evaluated would be much more helpful.
407-
sourceMaps: false
408-
}
380+
loader: 'happypack/loader?id=babelOutside',
409381
},
410382
// "postcss" loader applies autoprefixer to our CSS.
411383
// "css" loader resolves paths in CSS and adds assets as dependencies.
@@ -438,6 +410,24 @@ module.exports = function(webpackEnv) {
438410
getLocalIdent: getCSSModuleLocalIdent
439411
})
440412
},
413+
{
414+
test: lessRegex,
415+
exclude: lessModuleRegex,
416+
use: getStyleLoaders({
417+
importLoaders: 1,
418+
sourceMap: isEnvProduction && shouldUseSourceMap
419+
}, 'less-loader'),
420+
sideEffects: true
421+
},
422+
{
423+
test: lessModuleRegex,
424+
use: getStyleLoaders({
425+
importLoaders: 1,
426+
sourceMap: isEnvProduction && shouldUseSourceMap,
427+
modules: true,
428+
getLocalIdent: getCSSModuleLocalIdent
429+
}, 'less-loader')
430+
},
441431
// Opt-in support for SASS (using .scss or .sass extensions).
442432
// By default we support SASS Modules with the
443433
// extensions .module.scss or .module.sass
@@ -623,7 +613,70 @@ module.exports = function(webpackEnv) {
623613
formatter: isEnvProduction ? typescriptFormatter : undefined
624614
}),
625615
isEnvProduction && new CompressionPlugin(),
626-
// isEnvProduction && new BundleAnalyzerPlugin()
616+
new HappyPack({
617+
id: 'babelInside',
618+
threadPool: happyThreadPool, // 指定进程池
619+
loaders: [
620+
{
621+
loader: 'babel-loader',
622+
options: {
623+
customize: require.resolve('babel-preset-react-app/webpack-overrides'),
624+
625+
plugins: [
626+
[
627+
require.resolve('babel-plugin-named-asset-import'),
628+
{
629+
loaderMap: {
630+
svg: {
631+
ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]'
632+
}
633+
}
634+
}
635+
]
636+
],
637+
// This is a feature of `babel-loader` for webpack (not Babel itself).
638+
// It enables caching results in ./node_modules/.cache/babel-loader/
639+
// directory for faster rebuilds.
640+
cacheDirectory: true,
641+
cacheCompression: isEnvProduction,
642+
compact: isEnvProduction
643+
}
644+
}
645+
]
646+
}),
647+
new HappyPack({
648+
id: 'babelOutside',
649+
threadPool: happyThreadPool, // 指定进程池
650+
loaders: [
651+
{
652+
loader: 'babel-loader',
653+
options: {
654+
babelrc: false,
655+
configFile: false,
656+
compact: false,
657+
presets: [[require.resolve('babel-preset-react-app/dependencies'), { helpers: true }]],
658+
cacheDirectory: true,
659+
cacheCompression: isEnvProduction,
660+
661+
// If an error happens in a package, it's possible to be
662+
// because it was compiled. Thus, we don't want the browser
663+
// debugger to show the original code. Instead, the code
664+
// being evaluated would be much more helpful.
665+
sourceMaps: false
666+
}
667+
}
668+
]
669+
}),
670+
671+
isEnvProduction && new BundleAnalyzerPlugin(),
672+
new webpack.DllReferencePlugin({
673+
manifest: path.resolve(__dirname, '../dll/manifest.json')
674+
}),
675+
new AddAssetHtmlPlugin([
676+
{ filepath: path.resolve(__dirname, '../dll/react.js') },
677+
{ filepath: path.resolve(__dirname, '../dll/redux.js') },
678+
{ filepath: path.resolve(__dirname, '../dll/router.js') }
679+
])
627680
].filter(Boolean),
628681
// Some libraries import Node modules but don't use them in the browser.
629682
// Tell Webpack to provide empty mocks for them so importing them works.

config/webpack.dll.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const { resolve } = require('path')
2+
const webpack = require('webpack')
3+
const TerserPlugin = require('terser-webpack-plugin')
4+
5+
// webpack --config webpack.dll.js
6+
module.exports = {
7+
entry: {
8+
'react': ['react', 'react-dom'],
9+
'router': ['react-router-dom'],
10+
'redux': ['redux', 'react-redux', 'redux-thunk'],
11+
// 'antd': [
12+
// 'antd/lib/form',
13+
// 'antd/lib/steps',
14+
// 'antd/lib/input',
15+
// 'antd/lib/row',
16+
// 'antd/lib/col',
17+
// 'antd/lib/button',
18+
// 'antd/lib/message',
19+
// 'antd/lib/icon',
20+
// 'antd/lib/cascader',
21+
// 'antd/lib/checkbox',
22+
// 'antd/lib/modal',
23+
// 'antd/lib/upload',
24+
// 'antd/lib/progress',
25+
// ]
26+
},
27+
output: {
28+
filename: '[name].js',
29+
path: resolve(__dirname, '../dll'),
30+
library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
31+
},
32+
plugins: [
33+
new webpack.DllPlugin({
34+
name: '[name]_[hash]', // 映射库的暴露的内容名称
35+
path: resolve(__dirname, '../dll/manifest.json') // 输出文件路径
36+
})
37+
],
38+
mode: 'production',
39+
40+
// optimization: {
41+
// minimize: true,
42+
// minimizer: [
43+
// new TerserPlugin()
44+
// ]
45+
// }
46+
}

dll/manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"name":"redux_a329dac0fecfb27db22a","content":{"./node_modules/react/index.js":{"id":0,"buildMeta":{"providedExports":true}},"./node_modules/@babel/runtime/helpers/esm/extends.js":{"id":1,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/components/Context.js":{"id":2,"buildMeta":{"exportsType":"namespace","providedExports":["ReactReduxContext","default"]}},"./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js":{"id":3,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/prop-types/index.js":{"id":4,"buildMeta":{"providedExports":true}},"./node_modules/invariant/browser.js":{"id":8,"buildMeta":{"providedExports":true}},"./node_modules/object-assign/index.js":{"id":10,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/connect/wrapMapToProps.js":{"id":11,"buildMeta":{"exportsType":"namespace","providedExports":["wrapMapToPropsConstant","getDependsOnOwnProps","wrapMapToPropsFunc"]}},"./node_modules/react-is/index.js":{"id":12,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/hooks/useStore.js":{"id":13,"buildMeta":{"exportsType":"namespace","providedExports":["createStoreHook","useStore"]}},"./node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js":{"id":14,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/utils/Subscription.js":{"id":15,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/utils/shallowEqual.js":{"id":16,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/utils/useIsomorphicLayoutEffect.js":{"id":17,"buildMeta":{"exportsType":"namespace","providedExports":["useIsomorphicLayoutEffect"]}},"./node_modules/react/cjs/react.production.min.js":{"id":18,"buildMeta":{"providedExports":true}},"./node_modules/react-dom/index.js":{"id":19,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/components/connectAdvanced.js":{"id":20,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/utils/batch.js":{"id":21,"buildMeta":{"exportsType":"namespace","providedExports":["setBatch","getBatch"]}},"./node_modules/react-redux/es/utils/warning.js":{"id":22,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/hooks/useReduxContext.js":{"id":23,"buildMeta":{"exportsType":"namespace","providedExports":["useReduxContext"]}},"./node_modules/react-dom/cjs/react-dom.production.min.js":{"id":25,"buildMeta":{"providedExports":true}},"./node_modules/scheduler/index.js":{"id":26,"buildMeta":{"providedExports":true}},"./node_modules/scheduler/cjs/scheduler.production.min.js":{"id":27,"buildMeta":{"providedExports":true}},"./node_modules/prop-types/factoryWithThrowingShims.js":{"id":28,"buildMeta":{"providedExports":true}},"./node_modules/prop-types/lib/ReactPropTypesSecret.js":{"id":29,"buildMeta":{"providedExports":true}},"./node_modules/webpack/buildin/global.js":{"id":30,"buildMeta":{"providedExports":true}},"./node_modules/react-is/cjs/react-is.production.min.js":{"id":31,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/hooks/useDispatch.js":{"id":32,"buildMeta":{"exportsType":"namespace","providedExports":["createDispatchHook","useDispatch"]}},"./node_modules/react-redux/es/hooks/useSelector.js":{"id":33,"buildMeta":{"exportsType":"namespace","providedExports":["createSelectorHook","useSelector"]}},"./node_modules/redux/es/redux.js":{"id":34,"buildMeta":{"exportsType":"namespace","providedExports":["__DO_NOT_USE__ActionTypes","applyMiddleware","bindActionCreators","combineReducers","compose","createStore"]}},"./node_modules/react-redux/es/utils/reactBatchedUpdates.js":{"id":35,"buildMeta":{"exportsType":"namespace","providedExports":["unstable_batchedUpdates"]}},"./node_modules/symbol-observable/es/index.js":{"id":38,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/components/Provider.js":{"id":39,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/connect/connect.js":{"id":40,"buildMeta":{"exportsType":"namespace","providedExports":["createConnect","default"]}},"./node_modules/react-redux/es/utils/verifyPlainObject.js":{"id":41,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/symbol-observable/es/ponyfill.js":{"id":46,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/connect/mapDispatchToProps.js":{"id":47,"buildMeta":{"exportsType":"namespace","providedExports":["whenMapDispatchToPropsIsFunction","whenMapDispatchToPropsIsMissing","whenMapDispatchToPropsIsObject","default"]}},"./node_modules/react-redux/es/utils/isPlainObject.js":{"id":48,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/react-redux/es/connect/mapStateToProps.js":{"id":49,"buildMeta":{"exportsType":"namespace","providedExports":["whenMapStateToPropsIsFunction","whenMapStateToPropsIsMissing","default"]}},"./node_modules/react-redux/es/connect/mergeProps.js":{"id":50,"buildMeta":{"exportsType":"namespace","providedExports":["defaultMergeProps","wrapMergePropsFunc","whenMergePropsIsFunction","whenMergePropsIsOmitted","default"]}},"./node_modules/react-redux/es/connect/selectorFactory.js":{"id":51,"buildMeta":{"exportsType":"namespace","providedExports":["impureFinalPropsSelectorFactory","pureFinalPropsSelectorFactory","default"]}},"./node_modules/webpack/buildin/harmony-module.js":{"id":57,"buildMeta":{"providedExports":true}},"./node_modules/react-redux/es/index.js":{"id":58,"buildMeta":{"exportsType":"namespace","providedExports":["Provider","connectAdvanced","ReactReduxContext","connect","batch","useDispatch","createDispatchHook","useSelector","createSelectorHook","useStore","createStoreHook","shallowEqual"]}},"./node_modules/react-redux/es/connect/verifySubselectors.js":{"id":59,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/redux-thunk/es/index.js":{"id":60,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}}}}

0 commit comments

Comments
 (0)