美文网首页
webpack—— 优化输出质量

webpack—— 优化输出质量

作者: 黎明的叶子 | 来源:发表于2021-06-08 15:54 被阅读0次

    webpack 优化从两个方面入手。
    一、优化开发体检。包括优化构建速度和优化使用体验。参考链接优化开发体验
    二、优化输出质量,包括减少用户能感知到的加载时间(首屏加载时间)和提升流畅度(提升代码性能)。
    参考webpack官网深入浅出webpack

    减少用户能感知到的加载时间

    1. 压缩代码
      压缩后,代码文件会变小,且混淆。文件变小会使在网络中传输更优化一点。使用UglifyJS进行压缩。

    2. 代码分离
      代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以 按需加载或并行加载 这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
      代码分离是为了防止文件过大,多页面的时候有重复代码导入等原因。
      常用的代码分离方法有三种:

      • 入口起点:使用 entry 配置手动地分离代码。(也就是多页面配置,entry中有多个入口的情况下,打包出来的就是按照入口分离的。但是这种没有去除重复的。)
       // 1.入口起点   缺点:重复模块都会引入。比如lodash
        entry: {
            index: './src/index.js',
            another: './src/another-module.js',
        }, 
      
      • 防止重复:使用 SplitChunksPlugin 去重和分离 chunk。(替代了webpack3.0版本中的CommonsChunkPlugin)
        分离的方式是:
        多入口的时候:将公共的代码分离到一个默认为vendors的chunk里面。然后每个入口是一个chunk.比如我有两个入口 a.js 和 b.js 。那么打包出来的就是a.bundle.js 、 b.bundle.js、 vendors~a~b.bundle.js。
        单入口的时候:会按照设置规则打包。比如默认的设置这种。会将入口文件打包成一个文件比如index.bundle.js,将里面引用的比较大的文件,打包成单独的文件为vendors~index.bundle.js。
      // 2.防止重复  如果是多页面应用可以去重并分离。如果是单页面应用可以做到分离。 
      optimization: {
       splitChunks: {
           chunks: 'all'
       },
      },
      
      • 动态导入:通过模块中的内联函数调用来分离代码。动态引入的文件也会单独打包出来。
        包括两种方式。 第一种,推荐的,使用符合 ECMAScript提案的 import() 语法 来实现动态导入。第二种,则是 webpack 的遗留功能,使用 webpack 特定的 require.ensure。他们的原理就是利用JSONP。参考Webpack的异步加载原理及分包策略。动态导入完整代码参考官网介绍。
        动态导入的案例

    异步加载原理
    webpack ensure 有人称它为异步加载,也有人称为代码切割,他其实就是将 js 模块给独立导出一个.js 文件,然后使用这个模块的时候,再创建一个 script 对象,加入到 document.head 对象中,浏览器会自动帮我们发起请求,去请求这个 js 文件,然后写个回调函数,让请求到的 js 文件做一些业务操作。
    异步加载 就是动态导入。通过异步加载实现了按需加载。懒加载= 按需加载。依靠的方式是动态导入的方式

    1. 按需加载。就说用的时候才加载。框架里面的路由配置。多数都配置成路由按需加载。会自动生成对应的chunk。
    2. CDN 加速
      针对 HTML 文件:不开启缓存,把 HTML 放到自己的服务器上,而不是 CDN 服务上,同时关闭自己服务器上的缓存。自己的服务器只提供 HTML 文件和数据接口。
      针对静态的 JavaScript、CSS、图片等文件:开启 CDN 和缓存,上传到 CDN 服务上去,同时给每个文件名带上由文件内容算出的 Hash 值, 例如app_a6976b6d.css 文件。 带上 Hash 值的原因是文件名会随着文件内容而变化,只要文件发生变化其对应的 URL 就会变化,它就会被重新下载,无论缓存时间有多长。
      用 Webpack 实现 CDN 的接入。配置如下:
    const path = require('path');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const {WebPlugin} = require('web-webpack-plugin');
    
    module.exports = {
      // 省略 entry 配置...
      output: {
        // 给输出的 JavaScript 文件名称加上 Hash 值
        filename: '[name]_[chunkhash:8].js',
        path: path.resolve(__dirname, './dist'),
        // 指定存放 JavaScript 文件的 CDN 目录 URL
        publicPath: '//js.cdn.com/id/',
      },
      module: {
        rules: [
          {
            // 增加对 CSS 文件的支持
            test: /\.css$/,
            // 提取出 Chunk 中的 CSS 代码到单独的文件中
            use: ExtractTextPlugin.extract({
              // 压缩 CSS 代码
              use: ['css-loader?minimize'],
              // 指定存放 CSS 中导入的资源(例如图片)的 CDN 目录 URL
              publicPath: '//img.cdn.com/id/'
            }),
          },
          {
            // 增加对 PNG 文件的支持
            test: /\.png$/,
            // 给输出的 PNG 文件名称加上 Hash 值
            use: ['file-loader?name=[name]_[hash:8].[ext]'],
          },
          // 省略其它 Loader 配置...
        ]
      },
      plugins: [
        // 使用 WebPlugin 自动生成 HTML
        new WebPlugin({
          // HTML 模版文件所在的文件路径
          template: './template.html',
          // 输出的 HTML 的文件名称
          filename: 'index.html',
          // 指定存放 CSS 文件的 CDN 目录 URL
          stylePublicPath: '//css.cdn.com/id/',
        }),
        new ExtractTextPlugin({
          // 给输出的 CSS 文件名称加上 Hash 值
          filename: `[name]_[contenthash:8].css`,
        }),
        // 省略代码压缩插件配置...
      ],
    };
    

    以上代码中最核心的部分是通过 publicPath 参数设置存放静态资源的 CDN 目录 URL, 为了让不同类型的资源输出到不同的 CDN,需要分别在:

    • output.publicPath 中设置 JavaScript 的地址。
    • css-loader.publicPath 中设置被 CSS 导入的资源的的地址。
    • WebPlugin.stylePublicPath 中设置 CSS 文件的地址。

    提升流畅度

    1.使用 Prepack
    实际上 Prepack 就是一个部分求值器,编译代码时提前将计算结果放到编译后的代码中,而不是在代码运行时才去求值。
    Prepack 的工作原理和流程大致如下:
    通过 Babel 把 JavaScript 源码解析成抽象语法树(AST),以方便更细粒度地分析源码;
    Prepack 实现了一个 JavaScript 解释器,用于执行源码。借助这个解释器 Prepack 才能掌握源码具体是如何执行的,并把执行过程中的结果返回到输出中。
    从表面上看去这似乎非常美好,但实际上 Prepack 还不够成熟与完善。Prepack 目前还处于初期的开发阶段,局限性也很大。可以看官网或者看书。不再多做介绍。

    总结

    优化输出质量。就是更快的让用户能看到页面。一方面页面足够小(加载会快点,利用压缩),一次不要加载太多(解决首屏慢)。一方面则是利用网络可以一次请求4-7个请求。利用此特点,则不能全部放到一个文件中,合理的使用代码分离。进而可以做到按需加载。按需加载又解决了首屏慢的问题。另外通过cdn可以让用户访问最近的代码。加快请求。还可以做一些预加载之类的。
    在页面请求渲染的整个过程中,每一项都可以有优化的点。但是物极必反。合理的利用才是最好的选择。

    相关文章

      网友评论

          本文标题:webpack—— 优化输出质量

          本文链接:https://www.haomeiwen.com/subject/htzseltx.html