Junwen's home
  • ES6

    • ES6 Decorator
    • ES6核心特性
    • Promise&Generator
  • js原理

    • 简单实现bind、apply和call
    • 如何遍历一个dom tree
    • 实现函数currying
    • 实现一个event
    • 详解js的继承
    • 详解requestAnimationFrame
    • Canvas api详解
    • DOM事件
    • EventLoop详解
    • JavaScript的内存管理
    • JavaScript的运行机制
    • Math对象
    • new操作符都做了什么
    • create基本实现原理
    • Set、Map、WeakSet和WeakMap
    • web worker原理
    • WebGL教程(MDN)
  • jsInfoSeries

    • 简介
    • JavaScript基础知识
    • 基础知识2
    • 基础知识3
    • 基础知识4
  • 技巧

    • 5个js解构有趣用途
    • 如何使用set提高代码性能
    • cordova构建项目时的问题
    • js中轻松遍历对象属性的几种方式
  • 怎么写出更好的css
  • BFC详解
  • box-shadow详解
  • CSS小技巧
  • Grid布局详解
HTML
  • IP十问
  • http笔试
  • http协议
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • webpack

    • webpack HMR
    • webpack优化基本方法
  • leetcode题解

    • 两数之和
    • 判断整数是否为回文串
    • 无重复字符的最长子串
  • Js链表
  • JavaScript排序
  • React

    • 虚拟DOM原理理解
    • React Hook
    • 组件复用指南
  • Vue

    • Vue举一反三
面试题
读书笔记
GitHub (opens new window)

Syun0216

多读书多种树
  • ES6

    • ES6 Decorator
    • ES6核心特性
    • Promise&Generator
  • js原理

    • 简单实现bind、apply和call
    • 如何遍历一个dom tree
    • 实现函数currying
    • 实现一个event
    • 详解js的继承
    • 详解requestAnimationFrame
    • Canvas api详解
    • DOM事件
    • EventLoop详解
    • JavaScript的内存管理
    • JavaScript的运行机制
    • Math对象
    • new操作符都做了什么
    • create基本实现原理
    • Set、Map、WeakSet和WeakMap
    • web worker原理
    • WebGL教程(MDN)
  • jsInfoSeries

    • 简介
    • JavaScript基础知识
    • 基础知识2
    • 基础知识3
    • 基础知识4
  • 技巧

    • 5个js解构有趣用途
    • 如何使用set提高代码性能
    • cordova构建项目时的问题
    • js中轻松遍历对象属性的几种方式
  • 怎么写出更好的css
  • BFC详解
  • box-shadow详解
  • CSS小技巧
  • Grid布局详解
HTML
  • IP十问
  • http笔试
  • http协议
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • webpack

    • webpack HMR
    • webpack优化基本方法
  • leetcode题解

    • 两数之和
    • 判断整数是否为回文串
    • 无重复字符的最长子串
  • Js链表
  • JavaScript排序
  • React

    • 虚拟DOM原理理解
    • React Hook
    • 组件复用指南
  • Vue

    • Vue举一反三
面试题
读书笔记
GitHub (opens new window)
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • lerna学习笔记
  • 用nodejs搭建api网关
  • etcd学习
  • webpack

    • webpack HMR
    • webpack优化基本方法
      • webpack优化基本方法
      • 构建优化
      • 代码优化
      • js优化
  • CI/CD

    • 如何从0到1一步步成体系地搭建CI
    • 如何建立前端标准化研发流程
    • 如何打造全链路项目生命周期的统一交付平台
  • project
junwen
2020-05-18

webpack优化基本方法

# webpack优化基本方法

参考webpack优化的一些基本方法 (opens new window)

# 构建优化

# noParse(无序解析内部依赖包)

引入的第三方包如:jQuery,这些包内部是肯定不会依赖别的包,所以webpack不需要解析它的内部依赖关系,可以在webpack配置文件中的module属性下加上noParse,它是一个正则表达式,可以匹配无需解析的模块,这样可以节约webpack的打包时间,提高打包效率

module: {
  noParse: /jquery/
}
1
2
3

必须确保添加的包中没有依赖别的包,否则会报依赖错误

# DLLPlugin(动态链接库)

项目中依赖的一些第三方包比如react、vue一般情况下内容不会发生变化,所以不需要每一次都对它们进行构建,而是只需打包一次,之后直接引用就可以,知道第三方包需要更新版本时再重新进行构建。这样我们打包的时候只需要构建我们的业务代码即可。

Dllplugin插件可以帮助我们把这些不做修改的包抽取为动态链接库,并且会生成一个名为manifest.json的文件,这个文件是用来让DLLReferencePlugin映射到相关的依赖上去的。

以React为例抽取dll

  1. 创建抽取dll的webpack配置未见webpack.dll.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  mode: 'development',
  // 入口文件:将要配置成Dll的库放进来
  entry: {
    vendor: ['react','redux','react-router']
  },
  output: {
    // 输出文件名
    filename: '[name]_dll.js',
    // 输出文件路径
    path: path.resolve(__dirname, '../dist'),
    // 将打包好的文件暴露在全局
    library: '[name]_dll'
  },
  plugins: [
    new webpack.DllPlugin({
      //dll文件名
      name: '[name]_dll',
      //清单文件路径
      path: path.resolve(__dirname, '..dist/manifest.json')
    })
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  1. 配置DllReferencePlugin

这个插件一般是在webpack的主配置文件中配置,在plugins配置下添加如下配置,manifest文件会将dll文件的应用映射到模块的id上,然后在需要的时候来引用DLL文件。

new webpack.DllReferencePlugin({
  context: __dirname,
  manifest: path.resolve(__dirname, '../dist/manifest.json')
})
1
2
3
4
  1. 构建

package.json文件中添加:

scripts: {
  "build:dll": "webpack --config ./build/wepack.dll.js"
}
1
2
3

在命令行中运行该命令,这会在dist目录下生成react的Dll文件,还会生成一个mainfest.json文件,这个文件包含了import和require的request到模块id的映射。DLLReferencePlugin也会引用这个文件。然后再进行打包,就不会对react重复打包,而是直接引用生成的react_dll文件。

  1. 引入
<script src="./dist/vendor.dll.js"></script>
1

# 代码优化

# webpack自带优化

webpack的mode设置为production,进行生产模式打包时会自动进行以下优化:

  • tree shaking

webpack会在打包时移出引入了但未引用的代码,但是只有通过es6模块系统的import语法才有效,目的是减小生产环境下的文件体积,

  • scope hoisting

分析模块之间的依赖关系,会尽可能的将打散的模块合并到一个函数中去。也是只适用于es6的import和只被引用一次的模块

  • 代码压缩

所有代码自动使用UglifyJsPlugin进行压缩

# CSS优化

  • 将CSS拆分为独立文件

mini-css-extract-plugin可以将CSS拆分为单独的文件,使CSS文件可以被异步加载,加快页面加载呈现的速度。

  1. 安装插件
npm i mini-css-extract-plugin -D
1
  1. 修改主配置文件,使用该插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    ...,
    module: {
        rules: [
            ...,
            {
                test: /\.css$/,
                // 将原来多有使用style-loader来处理的地方替换为使用MiniCssExtractPlugin.loader
                // use: ['style-loader', 'css-loader'],
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        ...,
        new MiniCssExtractPlugin({
            // 生成的文件名
            filename: '[name].css'
        })
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • 压缩css

optimize-css-assets-webpack-plugin插件可以用来压缩CSS文件,但使用该插件会导致webpack默认的js压缩配置无法生效,所以还需要手动对js代码进行压缩,js压缩使用官方推荐的terser-webpack-plugin

  1. 安装插件
$ npm i optimize-css-assets-webpack-plugin terser-webpack-plugin -D
1
  1. 修改主配置文件,使用该插件
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
    ...,
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    }
}
1
2
3
4
5
6
7
8
9

# js优化

  • 拆分公共代码
Optimization: {
  splitChunks: {
    Chunks: 'all'
  }
}
1
2
3
4
5
  • IgnorePlugin(忽略插件)

有很多的第三方包内部会做国际化处理,包含很多的语言包,而这些语言包对我们来说时没有多大用处的,只会增大包的体积,我们完全可以忽略掉这些语言包,从而提高构建效率,减小包的体积。
以moment为例,首先找到moment中语言包所在的文件夹,然后在webpack配置文件中添加插件

// 该方法的两个参数都是正则,第一个参数表示要忽略的路径,第二个表示该资源所在目录,在该文件夹下引入的语言包都会被忽略
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
1
2

这时候moment使用默认语言英语,如果要使用别的语言,可以手动引入需要使用的语言包。

import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-CN')
1
2
3
  • 懒加载

在页面中有一些代码块可能并不是在页面初始化的时候就需要使用的,需要用户的某些操作出发才会使用,如果用户不触发这个操作那这个代码块可能永远不会被使用。我们可以将这些某个操作触发才会使用的代码块按需加载进来,而不是在页面创建的时候直接加载,这样可以加快初始页面的加载速度。

// 假设在页面中有一个id为btn的按钮,当点击这个按钮的时候需要对时间进行操作
const btn = document.querySelector('#btn')
btn.onclick = e => import(/* webpackChunkName: "moment" */ 'moment').then(module => {
    var moment = module.default;
    moment().format('YYYY-MM-DD')
})
1
2
3
4
5
6

但是使用懒加载会影响用户体验,所以在懒加载的同时可以使用魔法注释:Prefetching,可以在首页资源加载完毕后,空闲时间时,将动态导入的资源加载进来,这样即可以提高页面加载速度又保证了用户体验。

const btn = document.querySelector('#btn')
btn.onclick = e => import(/* webpackChunkName: "moment" *//* webpackPrefetch: true */ 'moment').then(module => {
    var moment = module.default;
    moment().format('YYYY-MM-DD')
})
1
2
3
4
5
在Github上编辑此页 (opens new window)
上次更新: 3/22/2021, 3:47:15 AM
webpack HMR
如何从0到1一步步成体系地搭建CI

← webpack HMR 如何从0到1一步步成体系地搭建CI→

最近更新
01
如何打造全链路项目生命周期的统一交付平台
04-10
02
如何建立前端标准化研发流程
04-10
03
如何从0到1一步步成体系地搭建CI
04-10
更多文章>
Theme by Vdoing | Copyright © 2019-2021 Syun
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式