zoukankan      html  css  js  c++  java
  • webpack指南(一)HRM+Tree Shaking

    参考:https://www.cnblogs.com/PasserByOne/p/12084323.html

    https://blog.csdn.net/qq593249106/article/details/84928595

    html-webpack-plugin

    index.html中有一个<script>标签,开始时指向output中的app.js. 当output中filename改为app.bundle.js时,为了能自动完成连接更改,需要使用html-webpack-plugin.

    clean-webpack-plugin

    由于之前代码示例都被遗留下来,导致/dist 文件夹相当杂乱。由于配置的改变,webpack 会生成新的文件放置在 /dist 文件夹中,但是 webpack 无法追踪到哪些文件是实际在项目中用到的。

    通常,在每次构建前清理 /dist 文件夹,是比较推荐的做法,是借助clean-webpack-plugin。

    由于官网没有进行及时更新,配置会报错。改正后的配置如下:

    1. 安装

    npm install clean-webpack-plugin --save-dev

    2. 配置文件

     1 const path = require('path');
     2   const HtmlWebpackPlugin = require('html-webpack-plugin');
     3 + const { CleanWebpackPlugin } = require('clean-webpack-plugin');
     4 
     5   module.exports = {
     6     entry: {
     7       app: './src/index.js',
     8       print: './src/print.js'
     9     },
    10     plugins: [
    11 +     new CleanWebpackPlugin(),
    12       new HtmlWebpackPlugin({
    13         title: 'Output Management'
    14       })
    15     ],
    16     output: {
    17       filename: '[name].bundle.js',
    18       path: path.resolve(__dirname, 'dist')
    19     }
    20   };

    ExtractTextPlugin 用于将 CSS 从主应用程序中分离。

    bundle-loader 用于分离代码并延迟加载所生成的 bundle。

    source map

    当 webpack 打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置。例如,如果将三个源文件(a.jsb.js 和 c.js)打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会简单地指向到 bundle.js。这并通常没有太多帮助,因为你可能需要准确地知道错误来自于哪个源文件。

    为了更容易地追踪错误和警告,JavaScript 提供了 source map 功能,将编译后的代码映射回原始源代码。如果一个错误来自于 b.js,source map 就会明确的告诉你。

    在开发环境下,增加如下配置:

    +   devtool: 'inline-source-map'

    webpack-dev-server

    提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading).

    npm install --save-dev webpack-dev-server

    添加一个 script 脚本,

    package.json

    +     "start": "webpack-dev-server --open"

    webpack.config.js中添加

        devServer: {
            contentBase: './dist',
        },

    在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。

    webpack-dev-server 可在内存中进行代码的编译和资源的提供,但并不写入磁盘,以此提高性能。

    模块热替换(Hot Module Replacement 或 HMR)

    启用HMR

    更新 webpack-dev-server 的配置,1.使用 webpack 内置的 HMR 插件;2.还要删除掉 print.js 的入口起点

    webpack.config.js

      const path = require('path');
      const HtmlWebpackPlugin = require('html-webpack-plugin');
      const CleanWebpackPlugin = require('clean-webpack-plugin');
    + const webpack = require('webpack');
    
      module.exports = {
        entry: {
    -      app: './src/index.js',
    -      print: './src/print.js'
    +      app: './src/index.js'
        },
        devtool: 'inline-source-map',
        devServer: {
          contentBase: './dist',
    +     hot: true
        },
        plugins: [
          new CleanWebpackPlugin(['dist']),
          new HtmlWebpackPlugin({
            title: 'Hot Module Replacement'
          }),
    +     new webpack.NamedModulesPlugin(),
    +     new webpack.HotModuleReplacementPlugin()
        ],
        output: {
          filename: '[name].bundle.js',
          path: path.resolve(__dirname, 'dist')
        }
      };

    修改 index.js 文件,以便当 print.js 内部发生变更时可以告诉 webpack 接受更新的模块。

    if (module.hot) {
        module.hot.accept('./print.js', function (){
            console.log('update the printME module!');
            myPrint();
        }) 
    }

    通过在命令行使用 npm run start 启动服务。然后修改print.js中console.log的内容,浏览器控制台打印结果如下:

    但是现在只成功了50%, 因为点击 button 按钮, 会发现输出还是之前的(‘I get called from print.js!’), 说明 print.js 虽然被修改了, 但在 index.js 上还没有替换为修改后的内容, 所以 button 绑定的还是之前的事件, 这里需要在检测到代码修改后, 用修改之后的js重新渲染页面:

    var element = component(); //改用一个element保存一下
    document.body.appendChild(element);
    
    if (module.hot) { //告诉 webpack 接受热替换的模块
        module.hot.accept('./print.js', () => {
            console.log('Accepting the updated printMe module!');
            document.body.removeChild(element); //删掉旧的element
            element = component(); //获得一个修改后的element
            document.body.appendChild(element); //重新插入到网页中
        })
    }

    HMR修改样式表 https://www.webpackjs.com/guides/hot-module-replacement/#hmr-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F%E8%A1%A8

    借助于 style-loader 的帮助,CSS 的模块热替换实际上是相当简单的。当更新 CSS 依赖模块时,此 loader 在后台使用 module.hot.accept 来修补<style> 标签。

    webpack.config.js

    +   module: {
    +     rules: [
    +       {
    +         test: /.css$/,
    +         use: ['style-loader', 'css-loader']
    +       }
    +     ]
    +   },

    index.js

    +  import './style.css';

    修改style.css中的内容,无需刷新就可改变页面的样式。

    其他代码和框架

    可以使 HMR 与各种框架和库(library)平滑地进行交互

    • React Hot Loader:实时调整 react 组件。
    • Vue Loader:此 loader 支持用于 vue 组件的 HMR,提供开箱即用体验。
    • Redux HMR:无需 loader 或插件!只需对 main store 文件进行简单的修改。

    Tree Shaking 移除 JavaScript 上下文中的未引用代码(dead-code)。

    新的 webpack 4 正式版本,扩展了这个检测能力,通过 package.json 的 "sideEffects" 属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "纯的"ES2015 模块,由此可以安全地删除文件中未使用的部分。

    math.js中有两个函数square和cube, 在index.js中只使用cube. 为了将未使用square函数从dist/index.bundle.js文件中移除,

    在package.json中,增加sideEffects字段。

    "name": "your-project",
    “version": "1.0.0",
    +    "sideEffects": false,

    含义为:当所有代码都不包含副作用,可以简单地将该属性标记为 false,以此告知 webpack,它可以安全地删除未用到的 export 导出.

    「副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。
    举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。

    如果代码中的一部分含有副作用,可以使用数组的形式将其排除在外。

    注意,任何导入的文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似 css-loader 并导入 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除。

    {
      "name": "your-project",
      "sideEffects": [
        "./src/some-side-effectful-file.js",
        "*.css"
      ]
    }

    最后,在webpack.config.js中修改模式,进行代码压缩

    mode: "production"

    再运行npm run build,此时,dist文件夹中的.js文件都是压缩精简过的了。 square 函数不再被引入,同时, cube 函数出现的是修改版本(function r(e){return e*e*e}n.a=r

    由此,bundle的体积得以减小。

    使用webpack打包工程化项目

    我们可以先进行tree-shaking,再进行编译,减少编译带来的副作用,从而增加tree-shaking的效果。

    首先我们需要去掉babel-loader,然后webpack打包结束后,再执行babel编译文件。使用webpack的plugin,让这个环节依旧跑在webpack的打包流程中,而不再是以loader的形式对单个资源文件进行操作,而是在打包最后的环节进行编译。

    这里贴一个热心网友提供的插件BabelMinifyWebpackPlugin

    参考:https://juejin.im/post/6844903549290151949

  • 相关阅读:
    android模拟器速度问题
    input.nextLine() 问题出错!
    android中的“visible ”、“invisible”、“gone”的区别(转载)
    为什么匿名内部类参数必须为final类型(转载)
    转载------------------关于android的一些技巧
    关于数据库的数据类型
    关于几个新的快捷键
    目标

    巨大bug
  • 原文地址:https://www.cnblogs.com/ceceliahappycoding/p/12248143.html
Copyright © 2011-2022 走看看