前端的代码分片,或者说是按需加载,本质上是由于前端页面越来越复杂,代码体积越来越大,程序员需要对页面资源的加载做细粒度的控制。按需加载当然是好东西,但是会让页面逻辑变得更加复杂。好在webpack出现,让按需加载变得简单多了。

我们来做一个简单的demo,完整代码
demo的功能很简单,单击一个按钮,然后去加载一个js文件并执行。

index.html文件:

<button id="btn">load script</button>

index.js文件

document.getElementById('btn').addEventListener('click',function(){
    require.ensure([],()=>{
        let hello = require('./Hello').default;
        hello();
    },'Hello')
})

Hello.js文件

export default function hello(){
    alert('hello.')
}

在 click 的事件处理函数中,通过 require.ensure标记分割点,然后加载Hello.js并赋值给变量hello,最后调用该方法。这里需要说一下的是require.ensure的第三参数,是这个分片chunk的name。如果不加这个参数,默认会以chunkid来命名该文件。这个参数在开发环境还是很有用的,毕竟1.js的文件名,让人很难定位文件。

由于 ES2015 Loader spec 定义了 import() 方法来在运行时动态的加载javascript文件,所以webpack也把import()作为split code的分割点。

如果想用酷炫的import()语法,还需要安装一个插件:
npm i babel-plugin-syntax-dynamic-import --save-dev。然后,就可以把上面的 index.js文件改成:

document.getElementById('btn').addEventListener('click',function(){
   import('./Hello').then((Hello) => {
        let hello = Hello.default;
        hello();
    }).catch(err => console.log('Failed to load moment', err))
})

import()支持promise语法,所以可以用catch来处理加载文件引起的异常。但是,它也有它的弱点,import()无法给这个文件命名(类似于require.ensure的第三个参数),这样打包出来的文件都是用数字来标示的,非常难以区分,在开发环境下,会使定位错误变的更加困难。

此外,这两种语法在引用文件时,文件路径都不可以是表达式。例如:

 require.ensure([],()=>{
        let path = './Hello';
        let hello = require(path).default;
        hello();
    },'Hello')

这样会报错,无法正常加载文件。


秋水易寒
488 声望18 粉丝

js全栈