前言

weback在web构建工具的激烈竞争中逐渐脱引而出。 无论是编译速度、报错提示、可扩展性等都给前端开发者耳目一新的感觉。本篇文章是个人对webpack的一点小研究总结。

webpack在开发者社区的反馈

类似gulp把自己定位为stream building tools一样,webpack把自己定位为module building system。
在webpack看来,所有的文件都是模块,只是处理的方式依赖不同的工具而已。

webpack同时也把node的IO和module system发挥的淋漓尽致。 webpack在配合babel(ES6/7)tsc(typescript)等DSL语言预编译工具的时候,驾轻就熟,为开发者带来了几乎完美的体验。

webpack整体架构(以webpack.config主要部分进行划分)

  1. entry: 定义整个编译过程的起点

  2. output: 定义整个编译过程的终点

  3. module: 定义模块module的处理方式

  4. plugin 对编译完成后的内容进行二度加工

  5. resolve.alias 定义模块的别名

webpack的核心module

无论你是jsx,tsx,html,css,scss,less,png文件,webpack一视同仁为module。并且每个文件[module]都会经过相同的编译工序 loader==> plugin。

关于以上这点,以如下一个简单的webpack.config文件为例。看下webpack会做什么

 1 module.exports =  {
 2         watch: true,
 3         entry: './index.js',
 4         devtool: 'source-map',
 5         output: {
 6             path: path.resolve(process.cwd(),'dist/'),
 7             filename: '[name].js'
 8         },
 9         resolve: {
10             alias:{ jquery: 'src/lib/jquery.js', }
11         },
12         plugins: [
13             new webpack.ProvidePlugin({
14                 $: 'jquery',
15                 _: 'underscore',
16                 React: 'react'
17             }),
18             new WebpackNotifierPlugin()
19         ],
20         module: {
21             loaders: [{
22                 test: /\.js[x]?$/,
23                 exclude: /node_modules/,
24                 loader: 'babel-loader'
25             },  {
26                 test: /\.less$/,
27                 loaders:['style-loader', 'css-loader','less-loader']
28             }, {
29                 test: /\.(png|jpg|gif|woff|woff2|ttf|eot|svg|swf)$/,
30                 loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
31             }, {
32                 test: /\.html/,
33                 loader: "html-loader?" + JSON.stringify({minimize: false })
34             } ]
35         }
36     };

webpack是如何处理如上webpack.config文件解析

1. 确定webpack编译上下文context

默认情况下就是node启动的工作目录process.cwd(),当然也可以在配置中手动指定context。

webpack在确定webpack.config中entry的路径依赖时,会根据这个context确定每个要编译的文件(assets)的绝对路径。

2.entry和output 确定webpack的编译起点和终点

顾名思义,entry定义webpack编译起点,入口模块。 对应的结果为compolation.assets

output定义webpack编译的终点,导出目录

3. module.loaders 和 module.test 确定模块预编译处理方式

以babel为例,当webpack发现模块名称匹配test中的正则/js[x]?的时候。

它会将当前模块作为参数传入babel函数处理,babel([当前模块资源的引用])

函数执行的结果将会缓存在webpack的compilation对象上,并分配唯一的id 。

以上的这一步,非常非常关键。唯一的id值决定了webpack在最后的编译结果中,是否会存在重复代码。
而缓存在compilation对象上,则决定了webpack可以在plugin阶段直接拿取模块资源进行二度加工。

4. plugin阶段发生在webpack的module.loader处理之后,一般用来做一些优化操作。

比如webpack.ProvidePlugin,它会在对编译结果再加工的操作过程中进行自定义的变量注入,当模块中碰到比如_这个变量的时候,webpack将从缓存的module中取出underscore模块加载进引用_的文件(compilation.assets)。
比如WebpackNotifierPlugin,它会在编译结果ready的时通知开发者,output已经就绪。

5.resolve.alias的作用就是对module模块提供别名,并没有什么特殊的。

【副作用】 webpack编译过程中的电脑卡慢?

在weback经历以上流程的时候,查看你的内存,你会发现,内存飙升!!!

这一般都是loader阶段,对DSL进行AST抽象语法树分析的时候,由于大量应用递归,内存溢出的情
况也是非常常见。

output目录不是一个渐进的编译目录,只有在最后compilation结果ready的时候,才会写入,造成开发者等待的时候,output目录始终为空。

【大招】 webpack将编译结果导出到output是怎么做到的,为啥output不是渐进的写入文件

如上,webpack在plugin结束前,将会在内存中生成了棵巨大的文件模块tree

这个阶段就是ready阶段,webpack写入output目录的分割点。

这棵树的枝叶节点就是所有的module[由import或者require为标志,并配备唯一moduleId],

这棵树的主枝干就是所有的assets,也就是我们entry中的东西。

这棵树也是webpackPlugin的处理的时候的arguments。

总结

好吧,对于开发者来说,整体而言webpack的编译过程细节比较多,但是大体的框架还是比较直观。

里面涉及到的类似DSL,AST的概念及模块缓存等等,在构建工具中还是比较常见的。

一切文件皆为模块也和react的一切都可以变为JS一样,对前端世界带来了新的开发理念。

anyway,写webpackPlugin相对于loader而言还是比较简单的。

在写plugin的过程可以对webpack有个更加直观的认识,鼓励多多尝试。

最后,案例一个之前写的一个 repowebpackPlugin编写
webpack官方文档

转载于:https://www.cnblogs.com/wyaocn/p/5805581.html

webpack编译流程漫谈相关推荐

  1. 小程序工程化实践(上篇)-- 手把手教你撸一个小程序 webpack 插件,一个例子带你熟悉 webpack 工作流程...

    本文基于 webpack 4 和 babel 7,Mac OS,VS Code 小程序开发现状: 小程序开发者工具不好用,官方对 npm 的支持有限,缺少对 webpack, babel 等前端常用工 ...

  2. webpack打包流程_了不起的 Webpack 构建流程学习指南

    最近原创文章回顾: <了不起的 tsconfig.json 指南> <了不起的 Webpack HMR 学习指南(含源码分析)> <<你不知道的 Blob>番 ...

  3. 一文读懂babel编译流程,再也不怕面试官的刁难了

    前言 Babel 是一个强大的 js 编译器.有了 Babel, 我们可以放肆的使用 js 的新特性,而不用考虑浏览器兼容性问题.不仅如此,基于 babel 体系,我们可以通过插件的方法修改一些语法, ...

  4. webpack 修改title_Webpack漫谈

    本文使用「署名 4.0 国际 (CC BY 4.0)」 许可协议,欢迎转载.或重新修改使用,但需要注明来源. 作者: 百应前端团队 @双鱼 https://juejin.im/user/3075189 ...

  5. 浅析C/C++编译流程

    更多博文,请看音视频系统学习的浪漫马车之总目录 C/C++编译 浅析C/C++编译本质 一篇文章入门C/C++自动构建利器之Makefile 升级构建工具,从Makefile到CMake 如果你愿意一 ...

  6. webpack 打包流程

    流程梳理 在开始之前我们先对于整个打包流程进行一次梳理. 这里仅仅是一个全流程的梳理,现在你没有必要非常详细的去思考每一个步骤发生了什么,我们会在接下来的步骤中去一步一步带你串联它们. 整体我们将会从 ...

  7. webpack编译提速:使用externals和DllPlugin

    本文提供使用externals和DllPlugin优化webpack编译的大体思路,它们的基本思想是将依赖的框架等模块从构建过程中移除,进而提高打包速度以及减小打包产物的体积,具体的操作可以自行查阅. ...

  8. C 语言编程 — 程序的编译流程

    目录 文章目录 目录 文章目录 C 程序的编译流程 预处理 编译 汇编 链接 编译多个源文件 文章目录 <C 语言编程 - GCC 工具链> <C 语言编程 - 程序的编译流程> ...

  9. 深入剖析 iOS 编译 Clang LLVM(编译流程)

    2019独角兽企业重金招聘Python工程师标准>>> 前言 iOS 开发中 Objective-C 和 Swift 都用的是 Clang / LLVM 来编译的.LLVM是一个模块 ...

  10. esp8266 SDK开发之编译流程

    最近刚完成自己8266的小项目,已经发布在github上,有兴趣的朋友可以看一下 github地址:esp-ujn 1. 通过MQTT协议与服务器交互 2. 内置HTTP服务器,支持通过浏览器进行参数 ...

最新文章

  1. Docker安装(Mac)
  2. 本地搭建docker私服
  3. ubuntu下eclipse打开window下的java文件,注释内容为乱码,解决方法
  4. sql sum条件求和_Hive中使用over()实现累积求和和滑动求和
  5. android与mysql的交互,与Android中的外部SQLite数据库进行交互.
  6. VTK:PolyData之Outline
  7. 技术管理者怎样跳出“泥潭”
  8. 看这玩意复习你还会挂科?《软件工程2篇》
  9. ogg 登录mysql报字符集_mysqldump之字符集问题解决
  10. Spring在SSH中的角色和作用
  11. js基础之动画(一)
  12. MVC模式在Java Web应用程序中的实现
  13. DSP的cmd文件详解
  14. 2020最火网络新词英文_2020年最流行的话 2020最火网络新词
  15. hashmap是单向链表吗_LRU(Least Recent Used) java 实现为这么采用HashMap+双向链表
  16. [解决方案]罗技POWERPLAY鼠标垫无法连接G703/G903/G403等鼠标
  17. C语言之结构体就这样被攻克了!(绝对值得收藏的文章)
  18. 3分钟短文:Laravel路子真野啊!路由昵称前缀中间件
  19. 360°环视(全景影像)系统发展趋势
  20. Csocket OnReceive接收数据部分(解决接收数据不全的问题+获取时间+将数据写入文本文档)

热门文章

  1. 二分法和牛顿迭代实现开根号函数:OC的实现
  2. iOS解决NSData转NSString后字符为空
  3. Windows Phone开发(14):数据模板 转:http://blog.csdn.net/tcjiaan/article/details/7350849...
  4. Response.ContentType 控制输出文件类型(讨论下载文件问题)
  5. 难道现在是保险业的高速发展期?
  6. OpenNebula概述
  7. codeforces590b//Chip 'n Dale Rescue Rangers//Codeforces Round #327 (Div. 1)
  8. centos配置网络
  9. 解决Linux Fedora 虚拟机root用户登录提示鉴定故障的问题
  10. sql 查询数据长度