• webpack编译流程漫谈


    前言

    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官方文档

  • 相关阅读:
    Google Authentication 机制原理
    ldap日志
    ldap + kerberos 整合
    kerberos
    U盘格式化后的恢复
    初始化脚本(Os_Init_Optimization.sh)
    拿到新机器,进行初始化和部署Nginx的过程
    python 列表生成式
    python 装饰器
    简单总结无线CPE、无线AP、无线网桥的不同之处【转】
  • 原文地址:https://www.cnblogs.com/wyaocn/p/5805581.html
Copyright © 2020-2023  润新知