浅谈webpack优化

时间: 2018-12-03阅读: 1959标签: webpack

由于前端的快速发展,相关工具的发展速度也是相当迅猛,各大框架例如vue,react都有自己优秀的脚手架工具来帮助我们快速启动一个新项目,也正式因为这个原因,我们对于脚手架中最关键的一环webpack相关的优化知之甚少,脚手架基本上已经为我们做好了相关的开发准备,但是当我们想要做一些定制化的优化操作时,对webpack的优化也需要有一定的了解,否则无从下手,接下来就让我们进入webpack的优化世界


构建速度提升

loader提升

loader是webpack中最重要的特性,由于webpack自身只支持JavaScript,因此需要一系列的loader来处理那些非JavaScript模块,因此在我们用webpack建项目的时候一定会使用一系列的loader,例如:vue-loader、sass-loader、babel-loader等等,就以babel-loader为例,来看具体配置:

module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader?cacheDirectory=true',
      options: {
        presets: ['@babel/preset-env'],
        plugins: ['@babel/transform-runtime']
      }
    }]
  }
  • 对于loader来说最常用的就是exclude属性,用来避免不必要的转译,上面通过exclude来避免对node_modules中js中进行转译来提升构建速度,但是这样带来的提升效果有限。
  • cacheDirectory是对babel-loader的转译结果进行缓存,之后的webpack进行构建时,都会去尝试读取缓存来避免高耗能的babel重新转译过程,cacheDirectory可以指定一个缓存目录或者指定为true,为true时将使用默认的缓存目录node_modules/.cache/babel-loader。
  • babel对一些公共方法使用了非常小的辅助代码,默认会注入到每一个需要的文件,这样就造成重复引入,这时候就需要像上面那样引入transform-runtime来告诉babel引入runtime来代替注入


第三方库优化

externals

externals提高构建速度的方法就是在构建时不会将指定的依赖包打包到bundle中,而是在运行时再从外部获取依赖,具体是怎么用的呢?来看个例子:

externals : {
  vue : "Vue",
  vueRouter : "VueRouter",
  vueResource : "VueResource",
  vuex : "Vuex"
},
<script type="text/javascript" src="https//xxxx/vue.famliy.1.1.0.min.js"></script>

上面的例子的将vue全家桶都配置在externals中,然后将压缩包合成一个js文件放在cdn上面,这样就不会在构建时将文件打包到bundle中,提升打包速度,同时cdn又可以做缓存,提高访问速度,美滋滋


DllPlugin

DllPlugin是用来干什么的呢?DllPlugin会将第三方包到一个单独文件,并且生成一个映射的json文件,打包的生成的文件就是一个依赖库,这个依赖不会随着你的业务代码改变而被重新打包,只有当它自身依赖的包发生变化时才会需要重新打包依赖库,接下来来看具体配置吧:

module.exports = {
  entry: {
    vendor: ['vue', 'vue-router', 'vue-resource', 'vuex']
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    library: '[name]_hash',
  },
  plugins: [
    new webpack.DllPlugin({
      name: '[name]_[hash]',
      path: path.join(__dirname, 'dist', '[name]-manifest.json'),
      context: __dirname
    })
  ]
}

首先我们需要一个如上面例子那样的dll配置文件,然后编译这个配置文件,生成一个vendor.js和一个映射文件vendor-manifest.json,然后再在我们的webpack配置文件中对进行配置:

plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require('./dist/vendor-manifest.json')
    })
  ]

这样就完成配置了,是不是很简单呢?赶紧动手试试吧


happypack

happypack这是个什么呢?我们都知道webpack是个单线程处理任务的,当又多个任务需要处理的时候,需要排队,那happypack就是用多线程来处理任务,通过并发处理来提高任务处理速度,那么这个需要怎么配置呢?来看具体例子:

const happypack = require('happypack')
// 创建并发池
const threadPool = happypack.ThreadPool({size: os.cpus().length})
module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'happypack/loader?id=happyBabel' // id对应happypack插件id
    }]
  },
plugins: [
    new happypack({
      id: 'happyBabel',
      threadPool: threadPool,
      loaders: ['babel-loader?cacheDirectory']
    })
  ],


减小构建体积

webpack-bundle-analyzer

这个相信大家都很熟悉,就是一个可视化工具,用来查看各个包的大小以及相互之间的依赖关系,配置方法也很简单,就和插件的配置一样,来看具体例子:

const bundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
plugins: [
    new bundleAnalyzerPlugin()
  ],


tree shaking

tree shaking指的是什么呢?通常指的是JavaScript上下文中未引用的代码,怎么理解呢?比如你引用了lodash包,里面有许多和JavaScript相关的便利方法,但你实际只用了其中的一两个,此时打包时如果把所有的方法都打进去了,是不是很浪费呢?tree shaking的概念就是去除多余代码。来看一个简单的例子:

import {plus} from './count'

console.log(plus(1, 2))
function plus(x, y) {
  return x + y
}
function minus(x, y) {
  return x - y
}
export {
  plus,
  minus
}
const path = require('path')

module.exports = {
  entry: {
    main: './src/index.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
  },
  mode: 'development'
}

如上例所示,在入口文件中我们引入count.js中plus方法,我们期望的当然是只会引入plus方法,而不是都引入,但往往不随人愿,来看结果:


你会发现编译后的代码中,整个count.js都被编译进去了,这时候你就需要tree shaking了,接下来看做tree shaking的具体方法


UglifyJsPlugin

这个插件大家一定都用过,使用UglifyJsPlugin就可以在构建的过程中对冗余的代码进行删除,在webpack4中只需要将上面mode的值改为production,就会启用UglifyJsPlugin,是不是很简单,或许你想知道webpack4中怎么自己配置UglifyJsPlugin,那就来看具体配置吧:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
optimization: {
    minimizer: [
      new UglifyJsPlugin({
        parallel: true,
        cache: true,
        uglifyOptions: {
          compress: {
            drop_console: true,
            reduce_vars: true
          },
          output: {
            comments: false,
            beautify: false
          }
        }
      })
    ]
  }

是的在webpack4中的UglifyJsPlugin是配置在optimization中的minimizer中的,配置是不很简单呢?赶紧动手尝试吧


按需加载(import)

这里的import是指webpack中的动态加载,它的语法和ES6中的动态加载语法一摸一样,这是官方推荐的按需加载的方式,还是上面tree shaking的例子,我们只想引入plus方法,我们来看具体怎么使用:

import('./count.js').then((count) => {
  console.log(count.plus(1, 2))
})

我们只需要将入口文件改成上面的形式,其他的都不要变就可以实现按需引入,是不是很简单呢?在vue中路由的按需加载也可以这么用,来看一个简单的例子:

function view (name) {
  return new Promise((resolve, reject) => {
    import('../views/' + name + '.vue')
      .then((res) => {
        resolve(res)
      }).catch(e => {
        reject('网络异常,请稍后再试')
      })
  }).catch(err => {
    throw new Error('err,组件加载失败')
  })
}

传入一个名字,动态引入对应目录的下的视图文件,这只是一个简单的例子,具体的使用形式还是依据具体的场景


总结

这篇文章简单的从构建速度和代码体积两个方面简单的介绍了webpack优化相关的方法,希望大家都能自己动手去写一写,毕竟只有实践出真知,更何况是编程。


来源:https://segmentfault.com/a/1190000017218108
作者:william


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/1478

18个webpack插件总有一款适合你的

何为插件(Plugin)?专注处理 webpack 在编译过程中的某个特定的任务的功能模块,可以称为插件。Plugin 是一个扩展器,它丰富了 webpack 本身,针对是 loader 结束后,webpack 打包的整个过程

webpack 构建多页面应用初探

如何使用webpack构建多页面应用,这是一个我一直在想和解决的问题。网上也给出了很多的例子,很多想法。猛一看,觉得有那么点儿意思,但仔细看也就那样。使用webpack这个构建工具,可以使我们少考虑很多的问题。

Webpack有哪些常见的Loader?

这里其实没什么太大意义,无非是想请你们亲自去看看自己项目到底用了哪些loader而已, 下面简单列出一些。style-loader 将css添加到DOM的内联样式标签style里

webpack常用插件_webpackPlugin插件总结

本地开发构建’自然离不开webpack,webpack想要工作,那它就需要各种插件的支持,有不少童鞋在平时的项目开发中使用过Webpack Plugins,这篇文章整理总结常用的webpackPlugin插件

什么是webpack?Webpack的核心概念

Webpack已经流行好久了,但很多同学使用webpack时还是一头雾水,一下看到那么多文档、各种配置、各种loader、plugin立马就晕头转向了。我也不例外,以至于很长一段时间对webpack都是一知半解的状态

vue+webpack4多页面打包配置

多页面配置通常有两种形式,一种是多页面多配置,一种是多页面单配置。因为webpack(3.1以上)可以直接处理一个配置对象的数组,所以可以为每个页面单独写一份配置。

通用、封装、简化 webpack 配置

现在,基本上前端的项目打包都会用上 webpack,因为 webpack 提供了无与伦比强大的功能和生态。但在创建一个项目的时候,总是免不了要配置 webpack,很是麻烦。简化 webpack 配置的一种方式是使用社区封装好的库,比如 roadhog。

Webpack有哪些常见的Plugin?他们是解决什么问题的

webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问

webpack中如何使用noParser和 parser

因为 Webpack 是以模块化的 JavaScript 文件为入口的,所以内置了对模块化 JavaScript的解析功能,支持 AMO, Cornmo nJS SystemJS ES6 parser 属性可以更细粒度地配置哪些模块语法被解析、哪些不被解析。同 noParse 配置项的区别在于

Webpack如何实现一个Loader?

loader定义: 用于对模块的源代码进行转换。loader 可以使你在 import 或\\\"加载\\\"模块时预处理文件,loader是一个node模块,编写loader时要遵循单一原则,每个loader只做一种\\\"转义\\\"工作

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!