浅谈webpack优化

时间: 2018-12-03阅读: 437标签: 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


webpack如何编译ES6打包

随着ES的普及我们越来越多的开始使用ES6的语法了,当然也随着mvvm框架的流行少不了js模块化,那js模块化又有那些呢?在很早的时候大家都用的命名空间,现在也有人用(库名.类别名.方法名)

webpack output

output输出口必须是个对象,因为它必须有两个属性:filename输出出去的文件的名字,一般都是bundle.js,path文件要输出出去到哪里,一般都是dist文件,那如果我们是多页面引用,那上面这个输出就不行了

Webpack 是怎样运行的?

在平时开发中我们经常会用到Webpack这个时下最流行的前端打包工具。它打包开发代码,输出能在各种浏览器运行的代码,提升了开发至发布过程的效率。主要包含入口(entry)、输出文件(output)、模式、加载器(Loader)、插件(Plugin)等几个部分

webpack Code Splitting浅析

Code Splitting是webpack的一个重要特性,他允许你将代码打包生成多个bundle。对多页应用来说,它是必须的,因为必须要配置多个入口生成多个bundle;对于单页应用来说,如果只打包成一个bundle可能体积很大,导致无法利用浏览器并行下载的能力

手把手教你写一个 Webpack Loader

webpack 只能理解 JavaScript 和 JSON 文件。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

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

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

vue+webpack4多页面打包配置

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

Webpack如何实现一个Loader?

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

用不同语言语法编写webpack配置文件

webpack配置文件默认情况下为webpack.config.js,即用原生js语法书写的配置文件。然而,在我们的项目中,有时候是使用的是其他语言语法进行编程,例如:es6、coffeeScript、typeScript等语言语法。

Webpack 打包含动态加载的类库

在编写库的时候,我们有时候会希望按需加载某些依赖,例如如果代码的运行环境不支持某些功能的话,就加载相关的Polyfill。webpack作为当前最流行的打包工具,早已支持动态加载的功能了。本文将讨论一种用webpack打包含动态加载的类库的方法。

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

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全