在前面的学习中,可以发现,js代码都打包成了一个文件。
这样使得js文件很大,影响加载速度,我们希望能将文件进行分割,这样可以实现多个文件并行加载,速度更快,另外代码分割之后还可以实现按需加载等功能。
代码分割方法一:通过入口文件进行代码分割
项目里面有两个js文件(index.js,test.js),可以通过设置entry实现多个入口,从而打包生成多个js文件。
// 单入口
// entry:'./src/js/index.js',
// 多入口
entry:{
main:'./src/js/index.js',
test:'./src/js/test.js'
},
output修改输出文件名filename:’js/[name].[contenthash:10].js’,
output: {
// 输出文件名
// filename: 'built.js',
// [name]:取entry中的文件名,如果entry中是main,则输出就是main,如果是test输出就是test
filename:'js/[name].[contenthash:10].js',
// 输出文件路径-写路径是要写绝对路径
// __dirname是nodejs的变量,代表当前文件的目录绝对路径,在这里当前文件指的就是webpack.config.js
// 第二个参数,当前路径下的哪个文件中,这里指的就是打包后的资源输出到当前路径下的build文件夹中
//连上上面的filename,就是打包资源输出到当前文件路径下的build文件夹中的built.js文件中
path: resolve(__dirname, 'build')
},
执行webpakc命令
可以看到打包生成了两个js文件。
但是这种方法有一点缺点:如果js文件名修改,或者js文件增加或者减少时,都需要修改配置很不方便。
代码分割方法二:通过splitChunks属性进行代码分割
单入口分析
不配置splitChunks
将入口文件还原为单入口,然后在index.js中引入jquery,
import '../css/style1.css'
import '../css/style2.less'
// import { test, test2, test3 } from './test.js'
import $ from 'jquery'
console.log('index.js执行了')
// test()
// test2([1, 2, 3])
function add(a, b) {
return a + b;
}
console.log(add(1, 3))
console.log($)
执行webpack命令:
在webpack.config.js中配置splitChunks
optimization:{
splitChunks:{
chunks:'all'
}
},
重新执行webpack
可以看到代码进行了分割。
splitChunks可以将node_modules中的代码单独打包成一个chunk输出
多入口分析
代码设置成多入口,并且在test中也引入jquery
import $ from 'jquery'
console.log($)
console.log('test.js执行了')
export function test() {
const value = 'hello world'
console.log('test value: ', value)
}
export function test2(arr) {
if (!arr || arr.length <= 0) {
console.log('test2 传参错误')
return
}
const result = arr.reduce((sum, current) => sum += current, 0)
console.log('test2 result: ', result)
}
export function test3(a, b) {
console.log('test3 执行力')
return a + b
}
不配置splitChunks
执行webpack命令
从打包后的文件大小可以看出,当多个入口都引入同一个库文件时,每个入口都会将库文件打包进去,这很不友好,如果整个项目只打包一次才是我们想要的。
在webpack.config.js中配置splitChunks
设置了splitChunks之后,再重新运行webpack命令
从打包输出文件可以明显看出jquery文件只打包了一次,并且输出了3个文件(一个node_modules库文件,两个入口文件)。这样项目的输出文件就减小了很多。
所以,splitChunks 会自动分析多个入口chunk中,有没有公共的文件,如果有则会打包成单独的一个chunk,而不会重复加载
代码分割方法三:通过js代码进行代码分割
将配置修改为单入口,这样虽然设置了splitChunks,但是也只会将node_modules中文件单独打包。
在index.js中引入test.js文件
import '../css/style1.css'
import '../css/style2.less'
import { test, test2, test3 } from './test.js'
import $ from 'jquery'
console.log('index.js执行了')
test()
test2([1, 2, 3])
function add(a, b) {
return a + b;
}
console.log(add(1, 3))
console.log($)
执行webpack:
可以看到只打包了jquery库文件和index.js文件,test.js并没有单独打包。我们希望能将test文件也单独打包,该怎么处理呢?可以通过js代码,让某个文件单独打包成一个chunk
修改test.js的引入方式
// import { test, test2, test3 } from './test.js'
import('./test').then((result) => {
console.log('test.js加载成功')
console.log('result:', result)
}).catch(() => {
console.log('test.js加载失败')
})
输出result中是es6的module,在module中有test.js中的方法,如果需要使用test.js中的方法,就需要直接传入方法
// import { test, test2, test3 } from './test.js'
import('./test').then(({ test, test2 }) => {
console.log('test.js加载成功')
// console.log('result:', result)
test()
test2([1, 2, 3])
}).catch(() => {
console.log('test.js加载失败')
})
这种方法就是通过import动态倒入语法,能将某个文件单独打包
但是,从打包的输出文件可以看出输出的名字不是我们想要的。我们希望能够指定文件名。
可以通过webpackChunkName来设置打包输出的文件名
// import { test, test2, test3 } from './test.js'
import(/*webpackChunkName:'test'*/'./test').then(({ test, test2 }) => {
console.log('test.js加载成功')
// console.log('result:', result)
test()
test2([1, 2, 3])
}).catch(() => {
console.log('test.js加载失败')
})
可以看到重新运行后的test.js的输出文件名已经是我们指定的路。