webpack常用构建优化策略小结

简介

读了《深入浅出webpack》总结一下常用的webpack的构建优化策略,可通过以下手段来提升项目构建时的速度

更精准的loader规则

将loader规则写清楚

仅让需要处理的文件,进入loader处理环节,如下

  rules: [{
   // 正则尽量准确
   test: /\.js$/,
   // 使用缓存,缓存后在文件未改变时编译会更快(缓存查找原理见补充1)
   use: ['babel-loader?cacheDirectory'],
   // 指定需要处理的目录
   include: path.resolve(__dirname, 'src')
   // 理论上只有include就够了,但是某些情况需要排除文件的时候可以用这个,排除不需要处理文件
   // exclude: []
  }]

更精准的查找目录

将查找路径设置精确

理论上我们项目的第三方依赖均应在自己的工程的node_modules下,所以我们可以设置查找目录,减少node的默认查找(默认查找方式见补充2)

module.exports = {
  resolve: {
    // 指定当前目录下的node_modules目录
    modules: [path.resolve(__dirname, 'node_modules')]
  }
}

更精准的扩展名

数量更多类型的文件尽量放在前面

平时写代码,我们都习惯直接写文件名,而不去写扩展名,那么解析则按照下面属性进行解析

module.exports = {
  extensions: ['.js', '.jsx', '.ts', '.tsx'],
}

默认值

extensions: [".js", ".json"]

使用动态链接库预编译大模块

使用动态链接库,提前编译大模块

原理请见补充3

新建一个文件webpack_dll.config.js,内容如下

const path = require('path');
const webpack = require('webpack');

// 复用的大模块放在这里,这样每次都不需要重新编译了
const vendors = [
 'react',
 'react-dom',
 'lodash'
];

module.exports = {
 mode: 'development',
 output: {
  path: path.resolve(__dirname, './dist'),
  filename: '[name].js',
  library: '[name]',
 },
 entry: {
  vendors,
 },
 plugins: [
  new webpack.DllPlugin({
   path: path.resolve(__dirname, './dist/manifest.json'),
   name: '[name]',
  }),
 ],
};

执行webpack --config webpack_dll.config.js进行首次编译(如果更新版本需要再次编译)

然后在你的webpack配置文件中引入manifest.json

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

多进程处理文件

使用HappyPack同时处理多个loader编译任务

为了发挥多核CPU电脑的功能,利用HappyPack将任务分发给多个子进程并发执行

const path = require('path');
const HappyPack = require('happypack');
// 共享5个进程池
const happyThreadPool = HappyPack.ThreadPool({ size: 5 });

module.exports = {
 entry: './src/index.js',
 output: {
  filename: 'bundle.js',
  path: path.resolve(__dirname, 'dist'),
 },
 module: {
  // noParse: [/react\.production\.min\.js$/],
  rules: [{
   test: /\.js$/,
   // 和下面插件id一直,happypack才可以找到
   use: ['happypack/loader?id=babel'],
   include: path.resolve(__dirname, 'src')
  }]
 },
 plugins: [
  // 插件可以实例化多个
  new HappyPack({
   // 与上面对应
   id: 'babel',
   // 实际要使用的loader
   loaders: ['babel-loader?cacheDirectory'],
   // 默认开启进程数
   threads: 3,
   // 是否允许happyPack打印日志
   verbose: true,
   // 共享进程数,如果你使用超过一个happyplugin,官方建议共享进程池
   threadPool: happyThreadPool
  })
 ],
};

原理见补充4

多进程压缩文件

使用ParallelUglifyPlugin多进程同时压缩文件

ParallelUglifyPlugin是在UglifyJS基础上,增加了多进出处理的能力,加快了压缩速度

import ParallelUglifyPlugin from 'webpack-parallel-uglify-plugin';

module.exports = {
 plugins: [
  new ParallelUglifyPlugin({
   test,
   include,
   exclude,
   cacheDir,
   workerCount,
   sourceMap,
   uglifyJS: {
   },
   uglifyES: {
   }
  }),
 ],
};

减少监听文件

减少监听文件

原理见补充5

当我们使用webpack的watch功能进行文件监听时,更好的方式是控制监听目录,如下,排除node_modules减少对该目录监听,减少编译所需要循环的文件,提高检查速度

module.export = {
  watchOptions: {
    ignored: /node_modules/
  }
}

其他没那么重要的优化

更精准的mainFields

默认的这个值查找方式见官网点击此处

看了下react和lodash,只有一个main,目前来看使用es6看来还不普遍,所以这个值目前可能不太重要

module.exports = {
  resolve: {
    mainFields: ['main']
  }
}

第三方库映射

为什么这个不重要,我发现react直接导出的index.js则是根据环境判断使用哪份代码,目测来看并不需要进行循环依赖的处理

通过依赖,则可以直接使用打包后代码,而不需webpack去循环依赖

 resolve: {
  mainFields: ["main"],
  alias: {
   'react': path.resolve(__dirname, './node_modules/react/cjs/react.production.min.js')
  }
 }

不使用inline模式的devServer

原理见补充6

默认情况下,应用程序启用内联模式(inline mode)。这意味着一段处理实时重载的脚本被插入到你的包(bundle)中,并且构建消息将会出现在浏览器控制台。

当使用inline模式时,devServer会向每个Chunk中注入一段重载的脚本代码,但是其实一个页面只需要一次,所以当Chunk过多时,可以将inline设置为false

module.export = {
  devServer: {
    inline: false
  }
}

补充

补充1-cacheDirectory原理

当有设置cacheDirectory时,指定的目录将用来缓存loader的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的Babel重新编译过程。如果设置了一个空值 (loader: 'babel-loader?cacheDirectory') 或者 true (loader: babel-loader?cacheDirectory=true),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。

补充2-node的默认查找方式

  • 查找当前目录下的node_modules目录,看是否有匹配项,如有,命中文件
  • 寻找父目录的下的node_modules,如有,命中文件
  • 按照这个规则一直往父目录搜索直到到根目录下的node_modules

补充3-动态链接库思想

大量项目中可以复用的模块只需要被编译一次,在之后的构建过程中被动态链接库包含的模块将不会重新编译,而是直接使用动态链接库中的代码。(注:如果升级依赖的模块版本,需要重新编译动态链接库)

补充4-HappyPack原理

webpack构建中,需要大量的loader转换操作,很耗时,由于nodejs是单线程的,如果想更好利用cpu的多核能力,可以开启多个进程,同时对文件进行处理;可以看到在配置文件中,我们每次将文件交给happypack-loader去处理,然后由happypack去调度来执行文件的处理(happypack采用哪个loaders进行处理,是通过id知道的)

补充5-文件监听原理

webpack会从入口触发,将所有的依赖项放到一个list里边,然后每次修改文件内容,回去遍历整个list里边的文件,看是否有编辑时间的变化,如果有的话则进行编译

补充6-自动刷新原理

  • 向要开发的网页中注入代理客户端代码,通过代理客户端去刷新整个页面(默认)
  • 将要开发的网页放进一个iframe,通过刷新iframe去看刷新效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 性能优化篇之Webpack构建速度优化的建议

    如何输出Webpack构建分析 输出Webpack构建信息的.json文件:webpack --profile --json > stats.json --profile:记录构建中的耗时信息 --json:以json格式输出构建结果,最后只输出一个json文件(包含所有的构建信息) web可视化查看构建分析:得到了webpack构建信息文件stats.json,如何进行很好的可视化查看? 方案一:通过可视化分析工具Webpack Analyse,是个在线Web应用,上传stats.json文件

  • 浅谈一个webpack构建速度优化误区

    问题描述 项目中使用了一个npm包a.前几天一直用得好好的,突然某次拉了别的分支代码后,就出Bug了. 第一反应是别人把这个包的版本变了.查看了下项目的package.json.package-lock.json文件,该模块和依赖模块的信息并没有改变,node_modules/a中的版本信息也和package.json中的对应. 一下子没了头绪,只好到node_modules中去调试一下. TL;DR; 拉到最后看总结 XD node_modules目录结构 项目中node_modules目录如

  • 浅谈webpack 构建性能优化策略小结

    背景 如今前端工程化的概念早已经深入人心,选择一款合适的编译和资源管理工具已经成为了所有前端工程中的标配,而在诸多的构建工具中,webpack以其丰富的功能和灵活的配置而深受业内吹捧,逐步取代了grunt和gulp成为大多数前端工程实践中的首选,React,Vue,Angular等诸多知名项目也都相继选用其作为官方构建工具,极受业内追捧.但是,随者工程开发的复杂程度和代码规模不断地增加,webpack暴露出来的各种性能问题也愈发明显,极大的影响着开发过程中的体验. 问题归纳 历经了多个web项目

  • 性能优化篇之Webpack构建代码质量压缩的建议

    Webpack构建速度优化基本优化完毕,接下来考虑的就是:线上代码质量的优化,即如何使用webpack构建出高质量的代码 Webpack构建流程:初始化配置参数 -> 绑定事件钩子回调 -> 确定Entry逐一遍历 -> 使用loader编译文件 -> 输出文件 提纲 本次优化构建代码质量基本技术: reactRouter按需加载: 公共代码提取,以及代码压缩: CDN接入: 开启gzip压缩: 接入treeShaking,剔除无用代码 开启Scope Hoisting (生产环境

  • 详解基于DllPlugin和DllReferencePlugin的webpack构建优化

    一个基于vue-cli webpack2模板创建的项目.项目中使用到了vue+vue-router+axios+muse-ui+iview 现在构建一次需要的时间大概是40s左右.真心受不了.虽然在开发过程中,我们不太需要关心构建时间.但是如果在开发hybridApp时,构建的次数就会增多. 一般我们可以把项目分为三部分. 分类 说明 变动频率 vendor_library 核心库 低 vendor 一般项目依赖 中等 code 业务逻辑 高 vendor_library:比如vue,vue-r

  • 详解vue-cli之webpack3构建全面提速优化

    前言 伴随着vue的全球化,已经各种vue的组件框架越来越完善,从早期的element-ui到vux,iview等越来越多高质量的项目,使用vue进行前端构建已然是一件工程化,模块化,敏捷化的事情 在这其中,相信很多人都会选择官方的vue-cli初始化工程模板,然后通过引入第三方组件框架和工具的方式进行开发构建,我个人也十分推崇这种做法.但是vue-cli初始化的项目模板毕竟是面向所有开发者的,在兼容性方面会有一定妥协.相信很多人都已经搜索过各类的webpack构建优化文章,但是很多不是版本太老

  • 详解组件库的webpack构建速度优化

    背景 在公司的主要工作是组件库(基于vue的ui组件库,类似element-ui)的开发,也已经有两个多月,期间一直觉得项目的开发构建太慢,每次开发打开开发环境需要 40s 左右,简直不能忍.前前后后尝试了各种优化手段,但是都不理想.终于在今天,找到了问题所在,构建速度提升了 50% 以上,现在只需要 17s 左右,整个心情都好了.现在记录一下所用到的各种优化手段,因为是开发环境,所以只考虑构建速度. 各种配置项的优化 主要是对一些loader添加 include exclude之类的小优化,其

  • 浅谈React + Webpack 构建打包优化

    本文介绍了React + Webpack 构建打包优化,分享给大家,具体如下: 使用 babel-react-optimize对 React 代码进行优化 检查没有使用的库,去除 import 引用 按需打包所用的类库,比如 lodash . echart 等 lodash 可以采用babel-plugin-lodash进行优化. 需要注意的是 在 babel-react-optimize 中使用了 babel-plugin-transform-react-remove-prop-types 这

  • webpack常用构建优化策略小结

    简介 读了<深入浅出webpack>总结一下常用的webpack的构建优化策略,可通过以下手段来提升项目构建时的速度 更精准的loader规则 将loader规则写清楚 仅让需要处理的文件,进入loader处理环节,如下 rules: [{ // 正则尽量准确 test: /\.js$/, // 使用缓存,缓存后在文件未改变时编译会更快(缓存查找原理见补充1) use: ['babel-loader?cacheDirectory'], // 指定需要处理的目录 include: path.re

  • MySQL 建表的优化策略 小结

    目录 1. 字符集的选择 1 2. 主键 1 3. 外键 2 4. 索引 2 4.1. 以下情况适合于创建索引 2 4.2. 以下的情况下不适合创建索引 3 4.3. 联合索引 3 4.4. 索引长度 4 5. 特殊字段 4 5.1. 冗余字段 4 5.2. 分割字段 4 5.3. BLOB和CLOB 5 6. 特殊 5 6.1. 表格分割 5 6.2. 使用非事务表类型 5 1. 字符集的选择 如果确认全部是中文,不会使用多语言以及中文无法表示的字符,那么GBK是首选. 采用UTF-8编码会占

  • webpack4.0打包优化策略整理小结

    本文介绍了webpack4.0打包优化策略整理小结,分享给大家,具体如下: webapck4 新特性介绍-参考资料 当前依赖包的版本 1.优化loader配置 1.1 缩小文件匹配范围(include/exclude) 通过排除node_modules下的文件 从而缩小了loader加载搜索范围 高概率命中文件 module: { rules: [ { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/, // 排除不处理的目录

  • vue和webpack项目构建过程常用的npm命令详解

    vue //最新稳定版 cnpm install vue //全局安装 vue-cli cnpm install --global vue-cli //创建一个基于 webpack 模板的新项目 vue init webpack my-project //进入项目目录,运行 cd my-project cnpm install cnpm run dev  webpack //全局安装webpack cnpm install -g webpack //安装到你的项目目录 cnpm install

  • PHP数据库编程之MySQL优化策略概述

    本文简单讲述了PHP数据库编程之MySQL优化策略.分享给大家供大家参考,具体如下: 前些天看到一篇文章说到PHP的瓶颈很多情况下不在PHP自身,而在于数据库.我们都知道,PHP开发中,数据的增删改查是核心.为了提升PHP的运行效率,程序员不光需要写出逻辑清晰,效率很高的代码,还要能对query语句进行优化.虽然我们对数据库的读取写入速度上却是无能为力,但在一些数据库类扩展像memcache.mongodb.redis这样的数据存储服务器的帮助下,PHP也能达到更快的存取速度,所以了解学习这些扩

  • Vue项目总结之webpack常规打包优化方案

    由于新建项目发版打包时间大概需要 30分钟 ,发版时 严重 拖慢 下班 时间,所以特意查看了相关文档来优化打包速度,争取早点下班,^_^. 分析打包文件 要优化,先分析.我们先要知道到底是哪里拖慢我们的打包速度呢? 打包后生成文件分析 可以利用 webpack-bundle-analyzer 插件来分析我们打包后生成的文件 安装 npm i webpack-bundle-analyzer -D 使用 修改 webpack.prod.conf.js 文件 const BundleAnalyzerP

  • 详解Spring Cloud Config采用Git存储时两种常用的配置策略

    由于Spring Cloud Config默认采用了Git存储,相信很多团队在使用Spring Cloud的配置中心时也会采用这样的策略.即便大家都使用了Git存储,可能还有各种不同的配置方式,本文就来介绍一下两种常用的配置策略. 第一种:多个项目公用一个Git仓库,用不同的目录区分项目 主要的配置项如下: spring.cloud.config.server.git.uri=https://github.com/dyc87112/config-repo.git spring.cloud.con

  • React Hooks常用场景的使用(小结)

    前言 React 在 v16.8 的版本中推出了 React Hooks 新特性.在我看来,使用 React Hooks 相比于从前的类组件有以下几点好处: 代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护: 组件树层级变浅,在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,而在 React Hooks

  • webpack-cli在webpack打包中的作用小结

    目录 webpack & webpack-cli webpack Introduction webpack-cli 详解 Reference webpack & webpack-cli webpack Introduction webpack 是一个静态的模块化打包工具,为现代的JavaScript应用程序服务 打包 bundler:webpack可以帮助我们进行打包,所以它是一个打包工具 静态的static:将代码打包成最终的静态资源(部署到静态服务器) 模块化module:webpac

随机推荐