• tree shaking


    ## 背景
    先来讲下本篇文章的背景,我在自己搭建脚手架的时候,使用css-loader 和 style-loader 处理样式,打包后,插入 style 的代码可以在打包后的js文件中找到,但是html文件中插入style标签的代码并没有生效,相应的,我的css代码也并没有生效
    ## 原因
    后来查了一下,因为我设置的模式(mode)是production,在webpack4.0以后,production模式下是自动开启tree shacking 的,关于tree shacking 对css的处理,可以参考官方文档的一段话(v 4.42.1)
    
    > 注意,任何导入的文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似 css-loader 并导入 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除:
    ```
    {
      "name": "your-project",
      "sideEffects": [
        "./src/some-side-effectful-file.js",
        "*.css"
      ]
    }
    ```
    
    ## Tree  Shacking 的一些概念
    
    
    ### Tree  Shacking是什么
    
    顾名思义,摇树,你可以将应用程序想象成一棵树。绿色表示实际用到的源码和 library,是树上活的树叶。灰色表示无用的代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。
    tree shaking 就是这样一个术语,用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。
    
    - 在不使用 Tree Shacking 的情况下,一个文件中,只要有一个方法被使用到了,整个文件都会被打包到bundle中去,使用后,只会把用到的那个方法打包进去
    - 依赖于 ES2015 模块系统中的静态结构特性,只有使用ES6的语法才支持
    
    ### Tree Shacking 机制
    
    首先了解一个概念,DCE(dead-code elimination),无用代码擦除,如以下几种代码:
    
    - 代码不可到达,永远不会被执行 
    - 代码执行的结果不会被用到
    - 代码只会影响到死变量(只写不读)
    - ...
    
    识别无用代码是利用的ES6模块的特点:
    
    - (import时)只能作为模块顶层的语句出现
    -  import的模块名只能是字符串常量
    -  import binding是无法擦除的
    
    
    识别出后,使用 uglifyjs 压缩插件在压缩阶段 在 bundle 中删除它们。
    
    
    ### 副作用
    
    在纯ES6代码中,我们做到这些是很容易的,然而,我们的项目无法达到这种纯度,所以,此时有必要向 webpack 的 compiler 提供提示哪些代码是“纯粹部分”。
    
    > 所谓纯粹部分,是与副作用代码相对,副作用这个概念来源于函数式编程(FP),纯函数是没有副作用的,也不依赖外界环境或者改变外界环境。纯函数的概念是:接受相同的输入,任何情况下输出都是一样的。
    
    > 非纯函数存在副作用,副作用就是:相同的输入,输出不一定相同(像是http请求函数)。或者这个函数会影响到外部变量、外部环境。
    
    > 函数如果调用了全局对象或者改变函数外部变量,则说明这个函数有副作用。
    
    > 在webpack的官方解释是:
    
    > 「副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。
    
    
    有多种方法可以设置让一些文件避免Tree  Shacking 的影响
    
    1、通过 package.json 的 "sideEffects" 属性来实现
    
    ```
    {
      "name": "your-project",
      "sideEffects": false
    }
    
    ```
    
    如同上面提到的,如果所有代码都不包含副作用,我们就可以简单地将该属性标记为 false,来告知 webpack,它可以安全地删除未用到的 export 导出,默认是这样设置的。
    
    如果你的代码确实有一些副作用,那么可以改为提供一个数组:
    
    ```
    {
      "name": "your-project",
      "sideEffects": [ // 标记为有副作用
        "./src/some-side-effectful-file.js",
        "*.css"
      ]
    }
    ```
    
    方法二:
    
    ```
    rules: [
                {
                    test: /.css$/,
                    use: [
                        'style-loader',
                        'css-loader'
                    ],
                    sideEffects: true // 标记为有副作用
               },
          ],
    
    ```
    
    
    还有其他通过插件标记的,感兴趣的可以了解一下

     

     

    参考文档: tree shaking 官方文档

  • 相关阅读:
    [洛谷P4513][题解]小白逛公园
    [洛谷P2564][题解][SCOI2009]生日礼物
    [洛谷P3384][题解]轻重链剖分
    [洛谷P2607][题解][ZJOI2008]骑士
    第一次个人编程作业
    第一次博客作业
    第一次个人编程作业
    第一次博客作业
    1.初识数据库系统
    1.计算机发展历程
  • 原文地址:https://www.cnblogs.com/jiumengmeng/p/12835493.html
Copyright © 2020-2023  润新知