加载项目时,不管那些代码有没有执行到,都会下载下来。如果说,我们只下载我们需要执行的代码话,那么可以节省相当大的流量。也就是我们所说的按需加载,这对于大型项目是相当有用的。
基本使用
webpack官网有详细的介绍,这里简单阐述下:
加载函数:
- require.ensure(dependencies,callback,chunkName)
这个方法可以实现js的按需加载,分开打包,webpack
管包叫chunk
,为了打包能正常输出,我们先给webpack
配置文件配置一下chunk文件输出路径:
- // webpack.config.js
- module.exports = {
- ...
- output: {
- ...
- chunkFilename: '[name].[chunkhash:5].chunk.js',publicPath: '/dist/'
- }
- ...
- }
每个chunk都会有一个ID,会在webpack内部生成,当然我们也可以给chunk
指定一个名字,就是require.ensure
的第三个参数。
注意: 如果这里不配置chunkFilename
,那么打包出来的名称是id加name。
配置文件中
[name] 默认是 ID,如果指定了chunkName则为指定的名字。
[chunkhash] 是对当前chunk 经过hash后得到的值,可以保证在chunk没有变化的时候hash不变,文件不需要更新,chunk变了后,可保证hash唯一,由于hash太长,这里截取了hash的5个字符。
demo展示
- // a.js
- console.log('a');
- // b.js
- console.log('b');
- // c.js
- console.log('c');
- // entry.js
- require.ensure([],() => {
- require('./a')
- require('./b')
- },'chunk1')
- if(false){
- require.ensure([],() => {
- require('./c')
- },'chunk2')
- }
将会打包出3个文件,基础包、chunk1 和 chunk2,但是chunk2在if判断中,而且永远为false,所以 chunk2 虽然打包了但永远不会被加载。
结合 react-router 按需加载
react-router本身有一套动态加载方案。
- const CourseRoute = {
- path: 'course/:courseId',getChildRoutes(location,callback) {
- require.ensure([],function (require) {
- callback(null,[
- require('./routes/Announcements'),require('./routes/Assignments'),require('./routes/Grades'),])
- })
- },getIndexRoute(location,require('./components/Index'))
- })
- },getComponents(location,require('./components/Course'))
- })
- }
- }
getChildRoutes
getIndexRoute
getComponents
实际操作
- const home = (location,callback) => {
- require.ensure([],require => {
- callback(null,require('modules/home'))
- },'home')
- }
- const blog = (location,require('modules/blog'))
- },'blog')
- }
- <Router history={history}>
- <Route path="/" component={App}>
- <Route path="home" getComponent={home}></Route>
- <Route path="blog" getComponent={blog}></Route>
- </Route>
- </Router>
能否将按需加载抽成公共函数?
答案:不可以。
因为require
函数太特别了,他是webpack
底层用于加载模块,所以必须明确的声明模块名,require
函数在这里只能接受字符串,不能接受变量 。