webpack使用require的一点注意事项

By
写代码

最近的项目需要兼容到IE9,所以在打完包之后,在虚拟机里使用IE9调试,发现个别页面会有报错:“Promise”未定义

webpack-chunk-config

很奇怪,因为这几个页面比较简单,代码就几十行,也根本没有用到promise。当时考虑到时间紧迫,就没有仔细想,匆匆忙忙地打了个babel-polyfill上去,补上了promise,把这个问题盖过去了。

同时,有一个比较在意的问题,就是打包的时候,出现一些0/1/2/3.js的文件。

webpack-chunk-config

从log来看,包含的内容是那几个页面用到的插件。

webpack-chunk-config

由于只有那么几个文件,并且不是所有公共模块都打包,所以并不是webpack提取出来的公共模块。所以……搜一下文档看看吧。

1、非入口(non-entry chunk)文件

在查找CommonsChunkPlugin这个插件的用法的时候,偶然看到output里有个字段是chunkfilename,试着改一下看看:chunkFilename: "js/[id].chunk.js",运行,之前的0.js变成了0.chunk.js

官方文档里面说,这个选项决定非入口(non-entry chunk)文件的名字,那么这些0/1/2/3.js就是这里所说的“非入口文件”了。

什么时候会产生非入口文件?

简单说,当使用了动态载入(dynamic importing)方式引用模块,使这些部分被分割(代码分割)出来,供按需加载使用。

同时,如果不指定名字,分割出来的代码会按0.js/1.js/2.js...这样命名。这些名字的指定位置,在output.chunkfilename这里配置,所以,如果你配置了chunkFilename:"js/[id].chunk.js",即会按0.chunk.js/1.chunk.js...这样的格式命名。至于何时引用,由webpack负责,不用显式调用。

2、动态引入(Dynamic Imports)

这里 有动态引入的介绍。

一般,import * as someModule from './dir/someModule.js'形式引入的模块都是静态(static)的,只能放在文件顶部,也就是说,不能被if条件或事件处理函数包裹来达到按需引入的目的。但是可以用import(moduleName)来达到动态引入的目的

所以,用import()的语法,可以解决按需引入、分状态引入、加入符号计算等情况。webpack有对这部分的支持说明

3、require(String)require([])的区别

意外的,发现了IE一直报错的原因

webpack-chunk-config

查找js文件,确实发现几处这样的写法

虽然没有使用require.ensure,但是使用了require(['./dir/module1','./dir/module2'])的语法,同require(String)虽然写法一样,但是意思却是不一样的。

require(String)

require是CommonJS支持的格式,也是Node支持的引入语法,该方法是同步的,格式如下

require([])

有点疑问,这个应该是RequireJS的语法,因为写的并不是require.ensure。但在本地使用的webpack里是支持的,能找到的一点资料在这里

require([])是AMD语法,webpack相关的介绍在 这里。语法在需要的时候才下载依赖的模块,值得注意的是,该语法异步的。

require.ensure是commonJS的语法,和require([])语法基本类似,不同点在于,require.ensure可以通过option来指定chunk名字,但是require([])只能遵循webpack配置文件默认的命名规则。

将代码里require的数组分别用require(或者import)分开,再次编译,发现0/1/2/3.js文件都消失了。并且在IE9调试,不再出现“Promise”未定义的错误。

4、该使用require还是import?

require是CommonJS的规范,是Node支持的语法。在ES6之前,所有的模块化使用的都是require语法,不管是node(CommonJS)、requireJsJ还是seajs。

import是ES6的语法,但是ES6目前还没有普及。关于二者的关系,可以看这里

引用上文中的结论:在目前阶段,二者没有本质区别,我们会使用babel来支持ES6,但是babel也是将ES6转码为ES5再执行,import语法会被转码为require。这也是为什么在模块导出时使用module.exports,在引入模块时使用import仍然起效,因为本质上,import会被转码为require去执行。

4

Comments: 1

  1. 真是事无巨细,什么都要面面俱到

    08月08日

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

:razz: