首頁 web前端 js教程 webpack4.0打包優化步驟詳解

webpack4.0打包優化步驟詳解

May 02, 2018 pm 04:44 PM
web 詳解

這次帶給大家webpack4.0打包優化步驟詳解,webpack4.0打包優化的注意事項有哪些,以下就是實戰案例,一起來看一下。

webapck4 新功能介紹-參考資料

目前依賴套件的版本

 

##1.最佳化loader配置

 

1.1 縮小檔案匹配範圍(include/exclude)

透過排除node_modules下的檔案從而縮小了loader載入搜尋範圍高機率命中檔案

  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/, // 排除不处理的目录
        include: path.resolve(dirname, 'src') // 精确指定要处理的目录
      }
    ]
  }
登入後複製

1.2 快取loader的執行結果(cacheDirectory)

cacheDirectory是loader的特定的選項,預設值是false。指定的目錄(use: 'babel-loader?cacheDirectory=cacheLoader')將用來快取loader的執行結果,並減少webpack建置時Babel重新編譯過程。如果設定一個空值(use: 'babel-loader?cacheDirectory') 或true(use: 'babel-loader?cacheDirectory=true') 將使用預設的快取目錄(node_modules/.cache/babel-loader),如果在任何根目錄下都沒有找到node_modules 目錄,將會降級回退到作業系統預設的暫存檔案目錄。

module: {
  rules: [
    {
      test: /\.js$/,
      use: 'babel-loader?cacheDirectory', // 缓存loader执行结果 发现打包速度已经明显提升了
      exclude: /node_modules/,
      include: path.resolve(dirname, 'src')
    }
  ]
}
登入後複製

2.resolve最佳化設定

2.1 最佳化模組尋找路徑resolve.modules

# Webpack的resolve.modules配置模組庫(即node_modules)所在的位置,在js 裡出現import 'vue' 這樣不是相對、也不是絕對路徑的寫法時,會去node_modules 目錄下找。但是預設的配置,會採用向上遞歸搜尋的方式去尋找,但通常專案目錄裡只有一個node_modules,且是在專案根目錄,為了減少搜尋範圍,可以直接寫明node_modules 的全路徑;同樣,對於別名( alias)的配置,亦當如此:

const path = require('path');
function resolve(dir) { // 转换为绝对路径
  return path.join(dirname, dir);
}
resolve: {
  modules: [ // 优化模块查找路径
    path.resolve('src'),
    path.resolve('node_modules') // 指定node_modules所在位置 当你import 第三方模块时 直接从这个路径下搜索寻找
  ]
}
登入後複製
配置好src目錄所在位置後,由於util目錄是在src裡面所以可以用下面方式引入util中的工具函數

// main.js
import dep1 from 'util/dep1';
import add from 'util/add';
登入後複製

2.2 resolve.alias 設定路徑別名

建立import 或require 的路徑別名,來確保模組引入變得更簡單。配置項目透過別名來把原始導入路徑映射成一個新的導入路徑此優化方法會影響使用Tree-Shaking去除無效代碼

例如,一些位於src/ 資料夾下的常用模組:

alias: {
 Utilities: path.resolve(dirname, 'src/utilities/'),
 Templates: path.resolve(dirname, 'src/templates/')
}
登入後複製
現在,取代「在導入時使用相對路徑」這種方式,就像這樣:

import Utility from '../../utilities/utility';
登入後複製
你可以這樣使用別名:

import Utility from 'Utilities/utility';
登入後複製
resolve: {
  alias: { // 别名配置 通过别名配置 可以让我们引用变的简单
    'vue$': 'vue/dist/vue.common.js', // $表示精确匹配
    src: resolve('src') // 当你在任何需要导入src下面的文件时可以 import moduleA from 'src/moduleA' src会被替换为resolve('src') 返回的绝对路径 而不需要相对路径形式导入
  }
}
登入後複製
也可以在給定物件的鍵後的末尾添加$,以表示精準匹配:

alias: {
  util$: resolve('src/util/add.js')
}
登入後複製
這將產生以下結果:

import Test1 from 'util'; // 精确匹配,所以 src/util/add.js 被解析和导入
import Test2 from 'util/dep1.js'; // 精确匹配,触发普通解析 util/dep1.js
登入後複製

2.3resolve.extensions

#當引入模組時不帶檔案後綴webpack會根據此配置自動解析確定的檔案後綴

  1. #後綴列表盡可能小

  2. 頻率最高的往前放

  3. 導出語句盡可能帶著字尾

  4. #
    resolve: {
      extensions: ['.js', '.vue']
    }
    登入後複製

3.module.noParse

#用了noParse的模組將不會被loaders解析,所以當我們使用的函式庫如果太大,並且其中不包含import require、define的調用,我們就可以使用這項配置來提升效能, 讓Webpack 忽略對部分沒採用

模組化的檔案的遞歸解析處理。

// 忽略对jquery lodash的进行递归解析
module: {
  // noParse: /jquery|lodash/
  // 从 webpack 3.0.0 开始
  noParse: function(content) {
    return /jquery|lodash/.test(content)
  }
}
登入後複製

4.HappyPack

HappyPack是讓webpack對loader的執行過程,從單一進程形式擴展為多進程模式,也就是將任務分解給多個子行程去並發的執行,子行程處理完後再把結果傳送給主行程。從而加速程式碼建置 與 DLL動態連結程式庫結合來使用更佳。

npm i happypack@next -D
登入後複製
webpack.config.js

const HappyPack = require('happypack');
const os = require('os'); // node 提供的系统操作模块
 // 根据我的系统的内核数量 指定线程池个数 也可以其他数量
const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().lenght})
module: {
  rules: [
    {
      test: /\.js$/,
      use: 'happypack/loader?id=babel',
      exclude: /node_modules/,
      include: path.resolve(dirname, 'src')
    }
  ]
},
plugins: [
  new HappyPack({ // 基础参数设置
    id: 'babel', // 上面loader?后面指定的id
    loaders: ['babel-loader?cacheDirectory'], // 实际匹配处理的loader
    threadPool: happyThreadPool,
    // cache: true // 已被弃用
    verbose: true
  });
]
登入後複製

happypack提供的loader,是对文件实际匹配的处理loader。这里happypack提供的loader与plugin的衔接匹配,则是通过id=happypack来完成。

npm run dev
登入後複製

5.DLL动态链接库

在一个动态链接库中可以包含其他模块调用的函数和数据,动态链接库只需被编译一次,在之后的构建过程中被动态链接库包含的模块将不会被重新编译,而是直接使用动态链接库中的代码。

  1. 将web应用依赖的基础模块抽离出来,打包到单独的动态链接库中。一个链接库可以包含多个模块。

  2. 当需要导入的模块存在于动态链接库,模块不会再次打包,而是去动态链接库中去获取。

  3. 页面依赖的所有动态链接库都需要被加载。

5.1 定义DLL配置

依赖的两个内置插件:DllPlugin 和 DllReferencePlugin

5.1.1 创建一个DLL配置文件webpack_dll.config.js

module.exports = {
  entry: {
    react: ['react', 'react-dom']
  },
  output: {
    filename: '[name].dll.js', // 动态链接库输出的文件名称
    path: path.join(dirname, 'dist'), // 动态链接库输出路径
    libraryTarget: 'var', // 链接库(react.dll.js)输出方式 默认'var'形式赋给变量 b
    library: '_dll_[name]_[hash]' // 全局变量名称 导出库将被以var的形式赋给这个全局变量 通过这个变量获取到里面模块
  },
  plugins: [
    new webpack.DllPlugin({
      // path 指定manifest文件的输出路径
      path: path.join(dirname, 'dist', '[name].manifest.json'),
      name: '_dll_[name]_[hash]', // 和library 一致,输出的manifest.json中的name值
    })
  ]
}
登入後複製

5.1.2 output.libraryTarget 规定了以哪一种导出你的库  默认以全局变量形式 浏览器支持的形式

具体包括如下:

  1. "var" - 以直接变量输出(默认library方式) var Library = xxx (default)

  2. "this" - 通过设置this的属性输出 this["Library"] = xxx

  3. "commonjs" - 通过设置exports的属性输出 exports["Library"] = xxx

  4. "commonjs2" - 通过设置module.exports的属性输出 module.exports = xxx

  5. "amd" - 以amd方式输出

  6. "umd" - 结合commonjs2/amd/root

5.1.3 打包生成动态链接库

webpack --config webpack_dll.config.js --mode production
登入後複製

在dist目录下 多出react.dll.js 和 react.manifest.json

  1. react.dll.js 动态链接库 里面包含了 react和react-dom的内容

  2. react.manifest.json 描述链接库(react.dll)中的信息

5.2 在主配置文件中使用动态链接库文件

// webpack.config.js
const webpack = require('webpack');
plugins: [
  // 当我们需要使用动态链接库时 首先会找到manifest文件 得到name值记录的全局变量名称 然后找到动态链接库文件 进行加载
  new webpack.DllReferencePlugin({
    manifest: require('./dist/react.manifest.json')
  })
]
登入後複製

5.3 将动态链接库文件加载到页面中

需要借助两个webpack插件

html-webpack-plugin 产出html文件

html-webpack-include-assets-plugin 将js css资源添加到html中 扩展html插件的功能

npm i html-webpack-plugin html-webpack-include-assets-plugin -D
登入後複製

配置webpack.config.js

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlIncludeAssetsPlugin = require('html-webpack-include-assets-plugin');
pluings: [
  new webpack.DllReferencePlugin({
    manifest: require('./dist/react.manifest.json')
  }),
  new HtmlWebpackPlugin({
    template: path.join(dirname, 'src/index.html')
  }),
  new HtmlIncludeAssetsPlugin({
    assets: ['./react.dll.js'], // 添加的资源相对html的路径
    append: false // false 在其他资源的之前添加 true 在其他资源之后添加
  });
]
登入後複製

此时react.dll.js和main.js被自动引入到页面中,并且dll文件在main.js之前加载

 

6.ParallelUglifyPlugin

这个插件可以帮助有很多入口点的项目加快构建速度。把对JS文件的串行压缩变为开启多个子进程并行进行uglify。

cnpm i webpack-parallel-uglify-plugin -D
登入後複製
// webpck.config.js
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins: [
  new ParallelUglifyPlugin({
    workerCount: 4,
    uglifyJS: {
      output: {
        beautify: false, // 不需要格式化
        comments: false // 保留注释
      },
      compress: { // 压缩
        warnings: false, // 删除无用代码时不输出警告
        drop_console: true, // 删除console语句
        collapse_vars: true, // 内嵌定义了但是只有用到一次的变量
        reduce_vars: true // 提取出出现多次但是没有定义成变量去引用的静态值
      }
    }
  });
]
登入後複製

执行压缩

webpack --mode production
登入後複製
登入後複製

7.Tree Shaking

剔除JavaScript中用不上的代码。它依赖静态的ES6模块化语法,例如通过impot和export导入导出

commonJS模块 与 es6模块的区别

commonJS模块:

1.动态加载模块 commonJS 是运行时加载 能够轻松实现懒加载,优化用户体验

2.加载整个模块 commonJS模块中,导出的是整个模块

3.每个模块皆为对象 commonJS模块被视作一个对象

4.值拷贝 commonJS的模块输出和函数的值传递相似,都是值得拷贝

es6模块

1.静态解析 es6模块时 编译时加载 即在解析阶段就确定输出的模块的依赖关系,所以es6模块的import一般写在被引入文件的开头

2.模块不是对象 在es6里,每个模块并不会当做一个对象看待

3.加载的不是整个模块 在es6模块中 一个模块中有好几个export导出

4.模块的引用 es6模块中,导出的并不是模块的值得拷贝,而是这个模块的引用

7.1 保留ES6模块化语法

// .babelrc
{
  "presets": [
    [
      "env", {
        modules: false // 不要编译ES6模块
      },
      "react",
      "stage-0"
    ]
  ]
}
登入後複製

7.2 执行生产编译 默认已开启Tree Shaking

webpack --mode production
登入後複製
登入後複製

什么是Tree Shaking?

有个funs.js 里面有两个函数

// funs.js
export const sub = () => 'hello webpack!';
export const mul = () => 'hello shaking!';
登入後複製

main.js 中依赖funs.js

// main.js
import {sub} from './funs.js'
sub();
登入後複製

在main.js只使用了里面的 sub函数 默认情况下也会将funs.js里面其他没有的函数也打包进来, 如果开启tree shaking 生产编译时

webpack --mode production //此时funs.js中没有被用到的代码并没打包进来 而被剔除出去了
登入後複製

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

jQuery可见性过滤器使用案例详解

键值字符串如何转化为json字符串(附代码)

以上是webpack4.0打包優化步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Win11管理員權限取得詳解 Win11管理員權限取得詳解 Mar 08, 2024 pm 03:06 PM

Windows作業系統是全球最受歡迎的作業系統之一,其新版本Win11備受矚目。在Win11系統中,管理員權限的取得是一個重要的操作,管理員權限可以讓使用者對系統進行更多的操作和設定。本文將詳細介紹在Win11系統中如何取得管理員權限,以及如何有效地管理權限。在Win11系統中,管理員權限分為本機管理員和網域管理員兩種。本機管理員是指具有對本機電腦的完全管理權限

Oracle SQL中的除法運算詳解 Oracle SQL中的除法運算詳解 Mar 10, 2024 am 09:51 AM

OracleSQL中的除法運算詳解在OracleSQL中,除法運算是一種常見且重要的數學運算運算,用來計算兩個數相除的結果。除法在資料庫查詢中經常用到,因此了解OracleSQL中的除法運算及其用法是資料庫開發人員必備的技能之一。本文將詳細討論OracleSQL中除法運算的相關知識,並提供具體的程式碼範例供讀者參考。一、OracleSQL中的除法運算

PHP模運算子的作用及用法詳解 PHP模運算子的作用及用法詳解 Mar 19, 2024 pm 04:33 PM

PHP中的模運算子(%)是用來取得兩個數值相除的餘數的。在本文中,我們將詳細討論模運算子的作用及用法,並提供具體的程式碼範例來幫助讀者更好地理解。 1.模運算子的作用在數學中,當我們將一個整數除以另一個整數時,就會得到一個商和一個餘數。例如,當我們將10除以3時,商數為3,餘數為1。模運算子就是用來取得這個餘數的。 2.模運算子的用法在PHP中,使用%符號來表示模

linux系統呼叫system()函數詳解 linux系統呼叫system()函數詳解 Feb 22, 2024 pm 08:21 PM

Linux系統呼叫system()函數詳解系統呼叫是Linux作業系統中非常重要的一部分,它提供了一種與系統核心互動的方式。其中,system()函數是常用的系統呼叫函數之一。本文將詳細介紹system()函數的使用方法,並提供對應的程式碼範例。系統呼叫的基本概念系統呼叫是使用者程式與作業系統核心互動的一種方式。使用者程式透過呼叫系統呼叫函數來請求作業系統

Linux的curl指令詳解 Linux的curl指令詳解 Feb 21, 2024 pm 10:33 PM

Linux的curl命令詳解摘要:curl是一種強大的命令列工具,用於與伺服器進行資料通訊。本文將介紹curl指令的基本用法,並提供實際的程式碼範例,幫助讀者更好地理解和應用該指令。一、curl是什麼? curl是命令列工具,用於發送和接收各種網路請求。它支援多種協議,如HTTP、FTP、TELNET等,並提供了豐富的功能,如檔案上傳、檔案下載、資料傳輸、代

如何從駕駛艙Web使用者介面啟用管理訪問 如何從駕駛艙Web使用者介面啟用管理訪問 Mar 20, 2024 pm 06:56 PM

Cockpit是一個面向Linux伺服器的基於Web的圖形介面。它主要是為了使新用戶/專家用戶更容易管理Linux伺服器。在本文中,我們將討論Cockpit存取模式以及如何從CockpitWebUI切換Cockpit的管理存取。內容主題:駕駛艙進入模式查找當前駕駛艙訪問模式從CockpitWebUI啟用Cockpit的管理訪問從CockpitWebUI禁用Cockpit的管理訪問結論駕駛艙進入模式駕駛艙有兩種訪問模式:受限訪問:這是駕駛艙的默認訪問模式。在這種存取模式下,您無法從駕駛艙Web用戶

深入了解Promise.resolve() 深入了解Promise.resolve() Feb 18, 2024 pm 07:13 PM

Promise.resolve()詳解,需要具體程式碼範例Promise是JavaScript中一種用來處理非同步操作的機制。在實際開發中,常常需要處理一些需要依序執行的非同步任務,而Promise.resolve()方法就是用來傳回一個已經Fulfilled狀態的Promise物件。 Promise.resolve()是Promise類別的靜態方法,它接受一個

web是什麼意思 web是什麼意思 Jan 09, 2024 pm 04:50 PM

web是全球廣域網,也稱為萬維網,是互聯網的一種應用形式。 Web 是一種基於超文本和超媒體的資訊系統,它允許使用者透過超連結在不同的網頁之間跳轉,從而瀏覽和獲取資訊。 Web 的基礎是互聯網,它使用統一、標準化的協定和語言,使得不同電腦之間能夠進行資料交換和資訊共享。

See all articles