zoukankan      html  css  js  c++  java
  • 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 官方文档

  • 相关阅读:
    c语言l博客作业04
    【 js 基础 】【 源码学习 】 深浅拷贝
    【 js 片段 】如何组织表单的默认提交?【亲测有效】
    【 js 性能优化】【源码学习】underscore throttle 与 debounce 节流
    【 js 片段 】移动端适配简易步骤
    【 js 模块加载 】【源码学习】深入学习模块化加载(node.js 模块源码)
    【 js 片段 】点击空白或者页面其他地方,关闭弹框
    【 js 算法类】这么全的数组去重,你怕不怕?
    【 js 工具 】如何使用Git上传本地项目到github?(mac版)
    【 js 工具 】如何在Github Pages搭建自己写的页面?
  • 原文地址:https://www.cnblogs.com/jiumengmeng/p/12835493.html
Copyright © 2011-2022 走看看