美文网首页
webpack优化

webpack优化

作者: 黄黄黄大帅 | 来源:发表于2020-09-22 19:03 被阅读0次

entry

应用程序入口

output

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist

loader

loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中

处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行
第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码

plugin

在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。

loader和plugin的区别

对于loader,它是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件转换过程

plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务

Webpack优化可以分为优化开发体验优化输出质量两部分

优化开发体验

1.优化构建速度
1-1 缩小文件搜索范围

在配置 Loader 时通过 include 去缩小命中范围

1-2 动态链接库Dll

为什么给 Web 项目构建接入 动态链接库 的思想后,会大大提升构建速度呢? 原因在于包含大量复用模块的动态链接库只需要编译一次,在之后的构建过程中被动态链接库包含的模块将不会在重新编译,而是直接使用动态链接库中的代码。 由于动态链接库中大多数包含的是常用的第三方模块,例如 react、react-dom,只要不升级这些模块的版本,动态链接库就不用重新编译。

1-3 使用 HappyPack

在整个 Webpack 构建流程中,最耗时的流程可能就是 Loader 对文件的转换操作了,因为要转换的文件数据巨多,而且这些转换操作都只能一个个挨着处理。(运行在 Node.js 之上的 Webpack 是单线程模型的)
HappyPack的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少了总的构建时间。

1-4 使用 ParallelUglifyPlugin

ParallelUglifyPlugin会开启多个子进程,把对多个文件的压缩工作分配给多个子进程去完成,每个子进程其实还是通过 UglifyJS去压缩代码,但是变成了并行执行。 所以 ParallelUglifyPlugin 能更快的完成对多个文件的压缩工作。

1-5 使用自动刷新

使用 webpack 模块负责监听文件,webpack-dev-server 模块则负责刷新浏览器。

1-6 开启模块热替换

1-7 externals

照官方文档的解释,如果我们想引用一个库,但是又不想让webpack打包,并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用,那就可以通过配置Externals。这个功能主要是用在创建一个库的时候用的,但是也可以在我们项目开发中充分使用Externals的方式,我们将这些不需要打包的静态资源从构建逻辑中剔除出去,而使用CDN的方式,去引用它们。
有时我们希望我们通过script引入的库,如用CDN的方式引入的jquery,我们在使用时,依旧用require的方式来使用,但是却不希望webpack将它又编译进文件中

// html中
<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous">
</script>
// webpack配置如下
module.exports = {
  //...
  externals: {
    jquery: 'jQuery'
  }
};
// jsx中引用
import $ from 'jquery';
$('.my-element').animate(/* ... */);
优化输出质量

1.区分环境

2.CDN 加速

3.Tree Shaking可以用来剔除 JavaScript 中用不上的死代码(没用到的代码)。它依赖静态的 ES6 模块化语法,例如通过 import 和 export 导入导出。

webpack 负责对代码进行标记,把 import & export 标记为 3 类:
1.所有 import 标记为 /* harmony import /
2.被使用过的 export 标记为 /
harmony export ([type]) /,其中 [type] 和 webpack 内部有关,可能是 binding, immutable 等等。
3.没被使用过的 import 标记为 /
unused harmony export [FuncName] */,其中 [FuncName] 为 export 的方法名称,之后在 Uglifyjs (或者其他类似的工具) 步骤进行代码精简,把没用的都删除。

4.提取公共代码
公共使用的是 jQuery 或者 Vue.js 这些体积较大的模块,不利于公共模块的缓存。
所以我们还需要把这些公共的模块提取到一个单独的 bundle 中。Webpack 中实现公共模块提取非常简单,我们只需要在优化配置中开启 splitChunks 功能就可以了,具体配置如下

// ./webpack.config.js
module.exports = {
  entry: {
    index: './src/index.js',
    album: './src/album.js'
  },
  output: {
    filename: '[name].bundle.js' // [name] 是入口名称
  },
  optimization: {
    splitChunks: {
      // 自动提取所有公共模块到单独 bundle
      chunks: 'all'
    }
  }
  // ... 其他配置
}

5.按需加载

// 路由懒加载
 {
            path: '/promisedemo',
            name: 'PromiseDemo',
            component: resolve => require(['../components/PromiseDemo'], resolve)
}
// import动态导入 和 魔法注释
import(/* webpackChunkName: 'posts' */'./posts/posts')
  .then(({ default: posts }) => {
    mainElement.appendChild(posts())
  })
// 组件懒加载:
components: {
    historyTab:resolve => {
       require(['../../component/historyTab/historyTab.vue'],resolve)
    },
},
 // webpack提供的require.ensure()
 {
            path: '/promisedemo',
            name: 'PromiseDemo',
            component: resolve => require.ensure([], () => resolve(require('../components/PromiseDemo')), 'demo')
        },
        {
            path: '/hello',
            name: 'Hello',
            // component: Hello
            component: resolve => require.ensure([], () => resolve(require('../components/Hello')), 'demo')
        }

相关文章

网友评论

      本文标题:webpack优化

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