We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本文主要说的是webpack编译中的make阶段,或者说webpack生成modules的整个流程。
webpack的make过程还是比较复杂的,主要流程如下
我认为make阶段的核心是依赖,实际上,make阶段的一切模块都由依赖构建出来。
首先是entry。我们在webpack的配置文件中可以指定entry,entry中指定的文件可以是单个、也可以是多个(字符串),举个entry给多个文件的例子(伪代码):
指定配置:: { entry: { main: ['./src/a', './src/b'], } } webpack:: const entryMainModule = { dependencies: { './src/a': Dep('./src/a'), './src/b':Dep('./src/b') }, // webpack的source是在make结束之后才被调用的 source() { return ` __webpack_require__(${this.dependencies['./src/a'].id}); module.exports = __webpack_require__(${this.dependencies['./src/b'].id}); `; } }
可以看出,webpack会把entry转换成一个新增的MultipleModule,entry数组里的模块被指定为依赖。当然如果是指定的单个文件,则entry直接转化为 NormalModule。不过还是会有转化为Dependency的过程。总结如下:
entry --> 是否单文件 --是--> entry设定为为SingleModuleDependency --> 生成NormalModule(会执行loader) | 否--> entry设定为MultipleModuleDependency --> 生成MultipleModule(无loader, parse)
造过构建工具轮子的人都知道,引用路径的处理是一块很麻烦的事情。webpack没有像babel他们,使用node的核心模块module, path等来简化一些处理,而是自己造了一个类Resolver, 这个类是支持插件的。不管是loader还是contextModule还是normalModule都是他处理,最后处理的结果都是把相对路径转化为绝对路径。(比较常规)
module
path
Resolver
由于loader也是Resolver解析的,所以loader的路径也就可以很灵活了,不一定非要放到node_modules里面(好像没人提这点)。
另外,resolve是比较蠢的,比如引用./a, 这货会同时找文件夹和文件,文件还会带上extension找。
./a
extension
此外,每个module都会独立地匹配loader,并不存在什么缓存。
webpack的loader有pitch特性, 所以
['style', 'picth-enabled', 'css']
加载loader的顺序是从左到右的,虽然执行的顺序是相反的。
loader可以指定raw属性,选择传过来的source是否是buffer。
loader具有一些很实用的方法可以调用,尤其是emitFile。emitFile的作用是给当前module附加一个assets(正常情况下assets其实是很后面的阶段才生成的),有没有一种钦定的赶脚。在我们常用的file-loader中就是用了这个特性。
emitFile
file-loader
很少有文章会提到webpack的parse,实际上这个才是真正意义上的“编译”嘛。在loader执行完之后,webpack会使用acorn将模块解析成ast,然后去遍历ast。
Parser模块支持插件,在遍历大多数语句的时候,都存在钩子。实际上给模块添加依赖就是遍历到"call commonjs:require"这种语句的时候,插件完成的,并且也将依赖模块的名字改为动态的了。
webpack的Parser相比babel还是很弱的。模块自身处理完了之后,都会去处理自身的依赖,也就是把依赖转化为模块。
module: { request: './src/a', context: 'xxxx', loaders: [], id: 0, // entry的id为0 source() {return xxxx}, dependencies: { './b': { request: './src/a', context: 'xxxx', module: module, } } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
本文主要说的是webpack编译中的make阶段,或者说webpack生成modules的整个流程。
1.核心
我认为make阶段的核心是依赖,实际上,make阶段的一切模块都由依赖构建出来。
首先是entry。我们在webpack的配置文件中可以指定entry,entry中指定的文件可以是单个、也可以是多个(字符串),举个entry给多个文件的例子(伪代码):
可以看出,webpack会把entry转换成一个新增的MultipleModule,entry数组里的模块被指定为依赖。当然如果是指定的单个文件,则entry直接转化为
NormalModule。不过还是会有转化为Dependency的过程。总结如下:
2. 对引用路径的处理
造过构建工具轮子的人都知道,引用路径的处理是一块很麻烦的事情。webpack没有像babel他们,使用node的核心模块
module
,path
等来简化一些处理,而是自己造了一个类Resolver
, 这个类是支持插件的。不管是loader还是contextModule还是normalModule都是他处理,最后处理的结果都是把相对路径转化为绝对路径。(比较常规)由于loader也是Resolver解析的,所以loader的路径也就可以很灵活了,不一定非要放到node_modules里面(好像没人提这点)。
另外,resolve是比较蠢的,比如引用
./a
, 这货会同时找文件夹和文件,文件还会带上extension
找。此外,每个module都会独立地匹配loader,并不存在什么缓存。
3. 对loader的处理
webpack的loader有pitch特性, 所以
加载loader的顺序是从左到右的,虽然执行的顺序是相反的。
loader可以指定raw属性,选择传过来的source是否是buffer。
loader具有一些很实用的方法可以调用,尤其是
emitFile
。emitFile
的作用是给当前module附加一个assets(正常情况下assets其实是很后面的阶段才生成的),有没有一种钦定的赶脚。在我们常用的file-loader
中就是用了这个特性。4. loader之后的parse
很少有文章会提到webpack的parse,实际上这个才是真正意义上的“编译”嘛。在loader执行完之后,webpack会使用acorn将模块解析成ast,然后去遍历ast。
Parser模块支持插件,在遍历大多数语句的时候,都存在钩子。实际上给模块添加依赖就是遍历到"call commonjs:require"这种语句的时候,插件完成的,并且也将依赖模块的名字改为动态的了。
webpack的Parser相比babel还是很弱的。模块自身处理完了之后,都会去处理自身的依赖,也就是把依赖转化为模块。
5. module的大致结构
The text was updated successfully, but these errors were encountered: