由于前端的快速发展,相关工具的发展速度也是相当迅猛,各大框架例如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

浅探webpack优化的更多相关文章

  1. 浅谈webpack优化

    webpack优化方案 1. 优化开发体验 1-1. 加快构建速度 ① 缩小文件搜索范围 由于 Loader 对文件的转换操作很耗时,需要让尽可能少的文件被 Loader 处理,用include和ex ...

  2. 浅谈SQL优化入门:3、利用索引

    0.写在前面的话 关于索引的内容本来是想写的,大概收集了下资料,发现并没有想象中的简单,又不想总结了,纠结了一下,决定就大概写点浅显的,好吧,就是懒,先挖个浅坑,以后再挖深一点.最基本的使用很简单,直 ...

  3. OCR技术浅探:基于深度学习和语言模型的印刷文字OCR系统

    作者: 苏剑林 系列博文: 科学空间 OCR技术浅探:1. 全文简述 OCR技术浅探:2. 背景与假设 OCR技术浅探:3. 特征提取(1) OCR技术浅探:3. 特征提取(2) OCR技术浅探:4. ...

  4. OCR技术浅探(转)

    网址:https://spaces.ac.cn/archives/3785 OCR技术浅探 作为OCR系统的第一步,特征提取是希望找出图像中候选的文字区域特征,以便我们在第二步进行文字定位和第三步进行 ...

  5. webpack快速入门——实战技巧:webpack优化黑技能

    1.抽离jquery,vue(多个第三方类库抽离) 修改入口文件(webpack.config.js中) entry: { entry: './src/entry.js', jquery:'jquer ...

  6. Webpack学习笔记九 webpack优化总结

    webpack 优化笔记 webpack4 自带的优化包括 swingTree(摇摆树)和作用域提升 swingTree 比如入口文件 index.js引入通用方法 util, 里面有 10个方法, ...

  7. font and face, 浅探Emacs字体选择机制及部分记录

    缘起 最近因为仰慕org-mode,从vim迁移到了Emacs.偶然发现org-mode中调出的calendar第一行居然没有对齐,排查一下发现是字体的问题.刚好也想改改Emacs的字体,于是我就开始 ...

  8. 常用的webpack优化方法

    1. 前言 关于webpack,相信现在的前端开发人员一定不会陌生,因为它已经成为前端开发人员必不可少的一项技能,它的官方介绍如下: webpack 是一个模块打包器.webpack的主要目标是将 J ...

  9. webpack优化之玩转代码分割和公共代码提取

    前言 开发多页应用的时候,如果不对webpack打包进行优化,当某个模块被多个入口模块引用时,它就会被打包多次(在最终打包出来的某几个文件里,它们都会有一份相同的代码).当项目业务越来越复杂,打包出来 ...

随机推荐

  1. HDU 1069 Monkey and Banana DP LIS变形题

    http://acm.hdu.edu.cn/showproblem.php?pid=1069 意思就是给定n种箱子,每种箱子都有无限个,每种箱子都是有三个参数(x, y, z)来确定. 你可以选任意两 ...

  2. Ubuntu搭建WordPress-MySQL-Apache

    目标 技术博客www.xifarm.com有5年时间了. 原来在虚拟机/VPS上搭建,不过都是Windows系统下的. 最近突发奇想,试试迁移到Linux的Unbuntu下.说干就干,抽空用了大约3天 ...

  3. WebApi访问方式配置

    之前公司使用webapi开发项目,只知道怎么用对于怎么配置一直不了解,最近这段时间没什么事然后自己建一个webapi项目,只知道怎么用对于怎么配置一直不了解,最近这段时间没什么事然后自己建一个weba ...

  4. .net的基础知识点

    在这个It市场都是风云变化的,都是又市场供需来定的,当年iOS火的一塌糊涂的,现在也出现找不到工作的,满地的出入门者,我就属于其中一个,在一个逼不得已的情况下,开始转行做.net ,我相信当年的很多. ...

  5. css position 定位模式

     定位 定位模式: static relative absolute fixed 边偏移 :top bottom left right 一般的定位必须要有定位模式以及边偏移 static 静态定位 默 ...

  6. querySelector/querySelectorAll

    querySelector获取页面I属性D为test的元素: document.getElementById("test"); //or document.querySelecto ...

  7. C++ 中函数后面跟const是什么意思

    问题:c++:void display( ) const 中的const是什么意思?简答:意思是除了表明了mutable的成员变量以外该类的其他的成员变量在这个函数内一律不能修改. 详细:加const ...

  8. android 代码将数据库文件导出到sd卡

    public static void save() { String dbpath = "/data/data/tl.cac.view/databases/" +"afi ...

  9. Jquery 日期差函数 修改 对火狐进行兼容

    function DateDiff(sDate1, sDate2) { //sDate1和sDate2是yyyy-MM-dd格式 var aDate, oDate1, oDate2, iDays; a ...

  10. ORA-02273: this unique/primary key is referenced by some foreign keys

    关于ORA-02273错误,以前还真没有仔细留意过.昨天遇到了这个问题,遂顺便总结一番,以后遇到这类问题就可以直接用下面方案解决.如下所示,我们首先准备一下测试环境. CREATE TABLE TES ...