webpack代码分离ensure(同步加载及异步)

前言

首先,webpack里的引入是使用require,导出是使用module.exports,也就是common.js规范。例如:

const path = require('path');

module.exports = {
 
    /*入口*/
    entry: [
        'react-hot-loader/patch',
        path.join(__dirname, 'src/index.js'),
    ],
    
    /*输出到dist文件夹,输出文件名字为bundle.js*/
    output: {
        path: path.join(__dirname, './dist'),
        filename: 'bundle.js'
    }
};

commonjs同步语法

经典的commonjs同步语法如下:

var a = require('./a');
a.show();

此时webpack会将a.js打包进引用它的文件中。这是最普遍的情形,不必赘述。

commonjs异步加载

在commonjs中有一个Modules/Async/A规范,里面定义了require.ensure语法。webpack实现了它,作用是可以在打包的时候进行代码分片,并异步加载分片后的代码。用法如下:

require.ensure([], function(require){
    var list = require('./list');
    list.show();
});

此时list.js会被打包成一个单独的chunk文件,大概长这样:

1.fb874860b35831bc96a8.js

可读性比较差。如果想给该文件指定打包文件的名字,那就是给require.ensure传递第三个参数,如:

require.ensure([], function(require){
    var list = require('./list');
    list.show();
}, 'list');

这样就能得到你想要的文件名称:

list.fb874860b35831bc96a8.js

注意:使用ensure进行打包,里面的代码是被打包到另外一个文件,如上面的list.js ,不是和主文件打包在一起。

你也可以传入像"question/list"这样带层级的名字,这样webpack会按照层级给你创建文件夹。

需要注意的是,如果你在require.ensure的函数中引用了两个以上的模块,webpack会把它们打包在一起,比如:


require.ensure([], function(require){
    var list = require('./list');
    list.show();
    var edit = require('./edit');
    edit.display();
}, 'list_and_edit')

list.js和edit.js将会被打包成一个文件,并命名为list_and_edit.js。这就需要根据你的实际情况来衡量了,如果你不希望打包在一起,只能写两个require.ensure分别引用这两个文件。

commonjs预加载懒执行

require.ensure(['./list'], function(require){
    var list = require('./list');
    list.show();
});

给require.ensure的第一个参数传了['./list'],执行到这里的时候list.js会被浏览器下载下来,但是并不会执行list.js模块中的代码,也就是webpack官网说的,不会进行evaluate。真正进行evaluate的时候是到了后面这句var list = require('./list');这就是所谓的懒执行。

写在函数中的多个模块会被打包在一起,这一点和上面没有区别。另外,写在数组中的模块也会跟他们打包在一起,不管你有没有手动执行。

AMD异步加载

webpack既支持commonjs规范也支持AMD规范,这就意味着AMD的经典语法是可以正常使用的,如:

require(['./list'], function(list){
    list.show();
});

当然,这样写的话list.js也是被单独打包成一个文件的。与上面类似,如果你在这里写了多个模块,那么这些模块都会被打包成一个文件,如:

require(['./list', './edit'], function(list, edit){
    list.show();
    edit.display();
});
list.js和edit.js会被打包在一起。不同的是,AMD的方式无法传入第三个参数当文件名,所以得不到很好看的文件。
//可打包在一起的同步代码,使用import语法
import list from './list';

//需要独立打包、异步加载的代码,使用require.ensure
require.ensure([], function(require){
    var list = require('./list');
});

import()

不过,现在在es6当中,import()加入了提案,我们可以动态加载模块。

import("./specifier.js"); // 返回 Promise

因此,我们可以使用then链,处理import完成后的文件。

import('./a.js').then(()=>{
  console.log('a.js is loaded dynamically');
});

import('./b.js').then((module)=>{
  const b = module.default;
  b('isDynamic');
});

import('./c.js').then(({c})=>{
  c('isDynamic');
});
  • 动态的 import() 提供一个基于Promise的API

  • import() 遵循ES模块规则:singleton,说明符,CORS等.

  • import() 可以在经典脚本和模块脚本中使用

  • 在代码中使用的import()的顺序与它们被解析的顺序没有什么共同之处



参考:https://www.cnblogs.com/lvdabao/p/5953884.html

https://cnodejs.org/topic/586823335eac96bb04d3e305

猜你喜欢

转载自blog.csdn.net/chiuwingyan/article/details/80666778