加载项目时,不管那些代码有没有执行到,都会下载下来。如果说,我们只下载我们需要执行的代码话,那么可以节省相当大的流量。也就是我们所说的按需加载,这对于大型项目是相当有用的。
基本使用
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
函数在这里只能接受字符串,不能接受变量 。