1. 代碼分割(Code Splitting)
1.1 CommonsChunkPlugin
-
CommonsChunkPlugin
可以進行同步代碼分割。 - 代碼結構
src/page/pageA.js
import './subPageA'
import './subPageB'
import lodash from 'lodash'
console.log('this is pageA')
src/page/pageB.js
import './subPageA'
import './subPageB'
import lodash from 'lodash'
console.log('this is pageB')
src/page/subPageA.js
import './module'
console.log('this is subPageA')
export default 'subPageA'
src/page/subPageB.js
import './module'
console.log('this is subPageB')
export default 'subPageB'
src/page/module.js
console.log('this is module')
export default "Module"
- 打包配置
//...
entry: {
pageA: './src/page/pageA',
pageB: './src/page/pageB',
vendor: ['lodash']
},
//...
plugins: [
//將pageA和pageB中公共代碼提出
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: 2,
chunks: ['pageA', 'pageB']
}),
//將lodash和webpack代碼分別提出
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest'],
minChunks: Infinity
})
]
CommonsChunkPlugin
可以將pageA
和pageB
這兩個入口文件中共同引入超過minChunks
次的模塊拆分出來,將webpack
打包代碼拆分出來,將第三方依賴模塊(lodash
)拆分出來,但不能對單個入口文件內部多次引入的模塊進行拆分。因爲需要設置多個入口文件,因此CommonsChunkPlugin
沒有webpack4.X
中的SplitChunksPlugin
好用。
1.2 異步代碼分割和懶加載
1.2.1 require.ensure
- 語法
require.ensure([dependencies], callback, errorCallback, chunkName)
引入模塊並可以執行。
require.ensure
依賴Promise
。如果瀏覽器不支持Promise
,需要添加polyfill
墊片。
- 編輯打包配置文件
webpack.config.js
entry: {
pageA: './src/page/pageA'
},
output: {
filename: '[name].[hash:5].bundle.js',
path: path.resolve(__dirname, 'dist'),
chunkFilename:'[name].[hash:5].js'
},
plugins: []
入口文件只有
pageA
。
需要配置chunkFilename
之後,require.ensure
中的第四個參數chunkName
纔會生效。
- 編輯代碼
src/page/pageA.js
var page = 'pageA'
if(page === 'pageA') {
require.ensure([], function () {
const subPageA = require('./subPageA')
}, 'subPageA');
} else {
require.ensure([], function () {
//require('./subPageB') 如果外部也引入了subPageB,則subPageB不會被單獨打包
const subPageB = require('./subPageB')
}, 'subPageB');
}
require.ensure([], function () {
const _ = require('lodash');
console.log(_.join([1,2,3], '-'))
}, 'vendor')
此時,subPageA
、subPageB
以及lodash
會被分割打包成單獨的包。
雖然subPageA
、subPageB
都被分割單獨打包,但是subPageB
不會被加載到頁面中。
如果外部也引入了
require.ensure
方法中通過require
引入的模塊,則該模塊不會分割單獨打包。
此時,由於subPageA
和subPageB
都引入了module
,因此module
被同時打包進了subPageA
和subPageB
。可通過require.include
解決此問題。
1.2.2 require.include
- 語法
require.include([dependencies])
如果兩個子模塊都引入一個第三方模塊,可在父模塊中使用require.include()
。這樣這個第三方模塊就不會同時打包進兩個子模塊中了。 - 編輯代碼
src/page/pageA.js
require.include('./module')
var page = 'pageA'
if(page === 'pageA') {
require.ensure([], function () {
const subPageA = require('./subPageA')
}, 'subPageA');
} else {
//require('./subPageB') 如果外部也引入了subPageB,則subPageB不會被單獨打包
require.ensure([], function () {
const subPageB = require('./subPageB')
}, 'subPageB');
}
require.ensure([], function () {
//會將lodash拆分打包成單獨的包(除非外部已經引入了lodash)
const _ = require('lodash');
console.log(_.join([1,2,3], '-'))
}, 'vendor')
export default 'pageA'
- 此時代碼打包會將
subPageA
和subPageB
中引入的module
打包進pageA
中。
1.2.3 import()
- 語法
import(
/* webpackChunkName: async-chunk-name */
/* webpackMode: lazy */
module
)
webpack
推薦使用import()
語法,不推薦使用require.ensure
。
- 安裝依賴
npm i @babel/plugin-syntax-dynamic-import -D
- 編輯
babel
配置
"plugins": [
"@babel/plugin-syntax-dynamic-import"
]
- 編輯代碼
require.include('./module')
var page = 'pageA'
if(page === 'pageA') {
import(/* webpackChunkName: 'subPageA' */ './subPageA').then(subPageA => {
console.log(subPageA)
});
} else {
import(/* webpackChunkName: 'subPageB' */ './subPageB').then(subPageB => {
console.log(subPageB)
})
}
import(/* webpackChunkName: 'vendor' */ 'lodash').then(lodash => {
console.log(lodash.join([1,2,3], '-'))
})
export default 'pageA'
只有配置chunkFilename
之後,webpackChunkName
才生效。
如果多個 import()
的魔法註釋webpackChunkName
指定同一個名字,則這多個import()
模塊會打包成一個bundle
。
如果外部也引入了import()
方法中引入的模塊,則該模塊不會分割單獨打包。
與
require.ensure
一樣,由於subPageA
和subPageB
都引入了module
,因此module
被同時打包進了subPageA
和subPageB
。通過require.include
解決此問題。
2. 加載樣式
2.1 [email protected] 配置項
- 安裝依賴
npm install --save-dev style-loader [email protected]
[email protected]
版本配置與@2.X
版本配置不同。
- 編輯打包配置文件
webpack.dev.config.js
{
test: /\.css$/,
use: [
"style-loader",
{
loader: 'css-loader',
options: {
minimize: true, //壓縮(失效)
modules: true, //開啓modules
localIdentName: '[path][name]__[local]--[hash:base64:5]'
}
}
]
}
X. mode
- 不支持
--mode development/production
或配置文件中的{mode: development/production}
定義開發模式和生產模式。