1. 程式人生 > >Webpack 配置詳解(含 4)——從 0 配置一套開發模板

Webpack 配置詳解(含 4)——從 0 配置一套開發模板

前言

原始碼

熟悉 webpack 與 webpack4 配置。

webpack4 相對於 3 的最主要的區別是所謂的零配置,但是為了滿足我們的專案需求還是要自己進行配置,不過我們可以使用一些 webpack 的預設值。同時 webpack 也拆成了兩部分,webpack 和 webpack-cli,都需要本地安裝。

我們通過實現一個 vue 的開發模板(vue init webpack 模板,其實跟 vue 關係不太大)來進行一次體驗。在配置過程中會盡量使用 webpack4 的相關內容。

本文不做 webpack 配置的完整介紹,著重介紹配置過程中需要注意的地方。檢視程式碼註釋閱讀效果更佳,完整配置與詳細註釋可見原始碼。配置位於 build 資料夾下。

與版本 4 相關的章節會新增符號 ④

需要注意的一點是,我們的 webpack 程式碼是執行在node環境下的,這部分程式碼可以使用 node api,但是我們的業務程式碼(src下)是無法使用 node api 的。

基本公用配置

由於 webpack 配置中的如 context,entry(chunk入口),output(輸出)和 module.rules 中 loaders 的配置在開發模式和生產模式基本都是公用的,所以我們提取到 webpack.base.js 檔案內,供複用。其中 output 部分如下:

output: {
  
  path: path.resolve(__dirname, '../dist/'
), // 資原始檔輸出時寫入的路徑 filename: 'static/js/[name].[chunkhash].js', // 使用 chunkhash 加入檔名做檔案更新和快取處理 chunkFilename: 'static/js/[name].[chunkhash].js' }

需要注意的有:

檔名 hash

hash 是用在檔案輸出的名字中的,如 [name].[hash].js,總的來說,webpack 提供了三種 hash:

  1. [hash]:此次打包的所有內容的 hash。
  2. [chunkhash]:每一個 chunk 都根據自身的內容計算而來。
  3. [contenthash]:由 css 提取外掛提供,根據自身內容計算得來。

三種 hash 的使用,我們在優化部分再講,先優先使用 [chunkhash]

loader 優先順序

loader 優先順序需要注意兩點,

  1. 同 test 配置內優先順序:在同一個 test 下配置多個 loader ,優先處理的 loader 放在配置陣列的後面,如對 less 處理,則:

    {
      test: /\.less$/,
      use: [
        'style-loader', 
        'css-loader', 
        'postcss-loader', 
        'less-loader'
      ]
    }
  2. 不同 test 內優先順序:如對 js 檔案的處理需要兩個 test 分別配置,使用 eslint-loader 和 babel-loader ,但是又不能配置在一個配置物件內,可使用 enforce: 'pre' 強調優先順序,由 eslint-loader 優先處理。

    {
      test: /\.(js|vue)$/,
      loader: 'eslint-loader',
      enforce: 'pre',
    },
    {
      test: /\.js$/,
      loader: 'babel-loader'
    }

css 前處理器配置

我們以 less 檔案的 loader 配置 ['vue-style-loader', 'css-loader', 'postcss-loader', 'less-loader'],使用 @import url(demo.less)為例:

  1. less-loader 先處理 less 語法
  2. postcss-loader 進行字首新增等其他處理
  3. css-loader 將內容引入 @import 所在的 css 檔案內
  4. vue-style-loader 將生成 style 標籤,將 css 內容插入 HTML

vue-style-loader 功能類似 style-loader

但是由於 vue 中的單檔案元件,又分為兩種情況:

  • .vue 檔案內的 style: 
    vue-loader 會對 .vue 單檔案元件進行處理,對 .vue 單檔案元件內的各種 lang="type" 我們可以在 vue-loader 的 options 配置不同的 loader,由於 vue-loader 內建了 postcss 對 css 進行處理,所以此處我們不需要再配置 postcss-loader

    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
        loaders: {
          less: ['// xxx-loaders'],
          scss: ['// xxx-loaders'],
        }
      }
    }
  • js 直接引入中引入樣式檔案: 
    如 main.js 中 import 'demo.less',這種方式引入的樣式檔案,在 vue-loader 處理範圍置之外,所以仍然需要配置 postcss-loader

由於這種差異我們將 對 css 前處理器檔案的配置封裝為函式,由 usePostCss 引數生成對應配置,將檔案放入 utils.js 檔案內,將 vue-loader 配置放在 vue-loader.js 檔案內。

也就是對 css 前處理器的配置我們需要在 vue-loader 內和 webpack 內配置兩遍。

寫這篇 README.md 期間 vue-loader 釋出了 v15 版,需要配合外掛使用,不用再進行兩遍配置

postcss-loader

postcss-loader 是一個強大的 css 處理工具,我們將 postcss 的配置拆分出去,新建 postcss.config.js 配置檔案

module.exports = {
  plugins: {
    // 處理 @import
    'postcss-import': {},
    // 處理 css 中 url
    'postcss-url': {},
    // 自動字首
    'autoprefixer': {
      "browsers": [
        "> 1%",
        "last 2 versions"
      ]
    }
  }
}

除了註釋中列出的需要的功能外掛,我們還可能會用到 nextcss(新的css語法的處理),px2rem/px-to-viewport 移動端適配相關的外掛。

babel-loader

我們使用 babel 編譯瀏覽器不能識別的 js、類 js 語法,如轉義 ES6+、JSX等。同樣將 babel-loader 的配置拆分出去,需要建立 .babelrc 並配置:

{
  "presets": [
    [
      /* *
       *  babel-preset-env
       *  可以根據配置的目標執行環境自動啟用需要的 babel 外掛。
       */
      "env", {
        "modules": false, // 關閉 babel 對 es module 的處理
        "targets": { // 目標執行環境
          "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
        }
      }
    ]
  ],
  "plugins": [
    "syntax-dynamic-import" // 非同步載入語法編譯外掛
  ]
}

媒體資源 loader

我們還需要對圖片、視訊、字型等檔案進行 loader 配置,以字型檔案為例子,主要用到的是 url-loader

{
  /**
   * 末尾 \?.* 匹配帶 ? 資源路徑
   * 我們引入的第三方 css 字型樣式對字型的引用路徑中可能帶查詢字串的版本資訊
   */
  test: /\.(woff2|woff|eot|ttf|otf)(\?.*)?$/,
  /**
   * url-loader
   * 會配合 webpack 對資源引入路徑進行復寫,如將 css 提取成獨立檔案,可能出現 404 錯誤可檢視 提取 js 中的 css 部分解決
   * 會以 webpack 的輸出路徑為基本路徑,以 name 配置進行具體輸出
   * limit 單位為 byte,小於這個大小的檔案會編譯為 base64 寫進 js 或 html
   */
  loader: 'url-loader',
  options: {
    limit: 10000,
    name: 'static/fonts/[name].[hash:7].[ext]',
  }
}

靜態檔案拷貝

直接引用(絕對路徑)和程式碼執行時確定的資源路徑應該是以靜態檔案存在的,這些資原始檔不會經過 webpack 編譯處理,所以我們將它們放在獨立的資料夾(如 static)中,並在程式碼打包後拷貝到我們的輸出目錄,我們使用 copy-webpack-plugin 自動完成這個工作:

const CopyWebpackPlugin = require('copy-webpack-plugin')

// 在開發模式下,會將檔案寫入記憶體
new CopyWebpackPlugin([
  {
    from: path.resolve(__dirname, '../static'),
    to: 'static',
    ignore: ['.*']
  }
])

此外掛在拷貝檔案過多時會崩潰,不知道解決了沒有。

生產模式 production

我們先進行生產模式的配置。

新增 script 指令碼命令

在 package.json 下新增

"scripts": {
  "build": "node build/build.js"`
}

那麼使用 npm run build 命令就可執行 node build/build.js,我們不直接使用 webpack webpack.prod.config.js 命令去執行配置檔案,而是在 build.js 中,做一些檔案刪除的處理,再啟動 webpack。

建立 build.js 邏輯

主要是兩個工作,引入 rimraf 模組刪除 webpack 下之前產生的指定檔案,啟動 webpack,並在不同階段給出不同的提示資訊。

// 在第一行設定當前為 生產環境
process.env.NODE_ENV = 'production'

const webpack = require('webpack')
const rm = require('rimraf')
const webpackConfig = require('./webpack.prod')
// 刪除 webpack 輸出目錄下的內容,也可只刪除子檔案如 static 等
rm(webpackConfig.output.path, err => {
  // webpack 按照生產模式配置啟動
  webpack(webpackConfig, (err, stats) => {
    // 輸出一些狀態資訊
  })
}

更多細節見原始碼註釋

生產模式配置檔案

新建 webpack.prod.js 檔案,使用

const merge = require('webpack-merge') // 專用合併 webpack 配置的包
const webpackBaseConfig = require('./webpack.base')
module.exports = merge(webpackBaseConfig, {
  // 生產模式配置
})

合併基本配置和生產模式獨有配置,然後我們開始進行生產模式下的 webpack 的配置資訊的填寫。

④ mode 預設

這是 webpack4 的新 api ,有三個預設值:developmentproductionnone,我們在生產模式選用mode: 'production',webpack4在此配置下預設啟用了:

  • 外掛

    • FlagDependencyUsagePlugin:應該是刪除無用程式碼的,其他外掛依賴
    • FlagIncludedChunksPlugin:應該是刪除無用程式碼的,其他外掛依賴
    • ModuleConcatenationPlugin:作用域提升 webpack3的scope hosting
    • NoEmitOnErrorsPlugin:遇到錯誤程式碼不跳出
    • OccurrenceOrderPlugin
    • SideEffectsFlagPlugin
    • UglifyJsPlugin:js程式碼壓縮
    • process.env.NODE_ENV 的值設為 production

所以這些預設啟用的內容我們不需要再配置。

最後一點設定 process.env.NODE_ENV 的值設為 production 其實是使用 DefinePlugin 外掛:

new webpack.DefinePlugin({
  "process.env.NODE_ENV": JSON.stringify("production") 
})

從而我們可以在業務程式碼中通過 process.env.NODE_ENV,如進行判斷,使用開發介面還是線上介面。如果我們需要在 webpack 中判斷當前環境,還需要單獨的設定 process.env.NODE_ENV = 'production',這也是我們在 build.js 中第一行做的事情。

新增 webpack 打出的 bundles 到 HTML 檔案

  • 我們使用 webpack 配置入口時只能配置 js 檔案作為入口,webpack 打出的 bundles 並不能自動與我們專案的 HTML 檔案發生關聯。
  • 需要我們手動新增<script src="./bundles.js"></script>(還可能包括後面提取出來的 css 檔案)到 HTML 檔案。
  • 當僅使用 webpack 對 js 進行打包,而沒有 HTML檔案需求時,不需要這一步。
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
  new HtmlWebpackPlugin({
    filename: path.join(__dirname, '../dist/index.html'),// 檔案寫入路徑
    template: path.join(__dirname, '../src/index.html'),// 模板檔案路徑
    inject: true // js 等 bundles 插入 html 的位置 head/body等
  })
]

如果不對 HtmlWebpackPlugin 進行配置,則其會建立一個 HTML 檔案,其中 filename 在開發模式下還是比較重要的。

④ 提取 js 中的 css 部分到單獨的檔案

使用過 webpack3 的同學應該對 extract-text-webpack-plugin 外掛(以舊外掛代稱)比較熟悉,為了嘗試webpack4,我並不想使用這個外掛的 @next 版本,所以選擇了新的替代外掛 mini-css-extract-plugin(以新外掛代稱)。 
與舊外掛相同,同樣需要在 webpack 的 loader 部分和 plugin 部分都進行配置,不同的是新外掛提供了單獨的 loader,在 loader 部分與舊外掛的配置方式不太相同。配置如下:

  • loader 部分

    const MiniCssExtractPlugin = require("mini-css-extract-plugin")
    // 
    [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          // (segmentfault 這兒的多行註釋渲染有點問題             

相關推薦

Webpack 配置 4—— 0 配置開發模板

前言原始碼熟悉 webpack 與 webpack4 配置。webpack4 相對於 3 的最主要的區別是所謂的零配置,但是為了滿足我們的專案需求還是要自己進行配置,不過我們可以使用一些 webpack 的預設值。同時 webpack 也拆成了兩部分,webpack 和 we

Logstash配置不斷更新

1. Input Plugin 1.1 從檔案輸入 從檔案讀取資料,如常見的日誌檔案。檔案讀取通常要解決幾個問題: No. 問題 解決辦法 1 檔案內容如何只被讀取一次?即重

CentOS 7.4 Tengine安裝配置

tengine nginx 一、安裝配置Tengine:Tengine是由淘寶網發起的Web服務器項目。它在Nginx的基礎上,針對大訪問量網站的需求,添加了很多高級功能和特性。Tengine的性能和穩定性已經在大型的網站如淘寶網,天貓商城等得到了很好的檢驗。它的最終目標是打造一個高效、穩定、安全、易

CentOS 7.4 Tengine安裝配置

tengine、虛擬主機、IP、訪問控制三、配置虛擬主機:1、配置基於端口的虛擬主機:(1)在http{}配置段中新增如下server:server {listen 8000;server_name localhost;access_log /usr/local/tengine/logs/localhost8

CentOS 7.4 Tengine安裝配置

location、echo、fancy九、根據HTTP響應狀態碼自定義錯誤頁:1、未配置前訪問一個不存在的頁面:http://192.168.1.222/abc/def.html,按F12後刷新頁面2、在server{}配置段中新增如下location:server {listen 80;server_nam

CentOS 7.4 Tengine安裝配置

tengine nginx https 十四、配置Tengine支持HTTPS1、演示環境:IP操作系統角色 192.168.1.222 CentOS 7.4 Tengine服務器 192.168.1.145 CentOS 6.9 自建CA服務器備註:Teng

CentOS 7.4 Tengine安裝配置

tengine 反向代理 十五、反向代理:1、演示環境:IP操作系統節點角色192.168.1.222CentOS 7.4node1Tengine服務器192.168.1.144CentOS 6.9node2Apache服務器2、node2安裝Apache服務,並創建測試頁:# yum -y inst

CentOS 7.4 Tengine安裝配置

tengine cache purge 十六、緩存及緩存清理1、修改node1配置文件nginx.conf:(1)在http配置段中增加如下代碼:proxy_cache_path /usr/local/tengine/cache levels=1:1:2 keys_zone=mycache:200

Tmocat的service.xml配置文件中文翻譯

bean ssl eth call 項目 redirect 類型 describe update Tmocat的service.xml配置文件 英文原版 中文手譯 <?xml version=‘1.0‘ encoding=‘utf-8‘?&g

Webpack配置package.json/webpack.config.js詳細配置

Webpack配置詳解(package.json/webpack.config.js詳細配置 ) webpack安裝 package.json配置以及模組安裝 webpack.config.js配置 開啟webpack-dev-server服務 熱替換外掛的安裝以及配置 開啟自動開啟瀏覽器外

Redis集群之配置文件待完善

enable ice local ise bare config 停止 databases end 運維Redis集群的核心任務就是配置文件Redis.conf 命令行將現使用的Redis配置參數導出到 redis.conf.bak文件 grep ‘^[^#]‘ /etc

log4j的配置

version let imp err pro 字符 bug rom 程序 轉自:http://blog.sina.com.cn/s/blog_5ed94d710101go3u.html 最近使用log4j寫log時候發現網上的寫的都是千篇一律,寫的好的嘛不

php文件上傳原理源碼

輸入數據 最大值 cut 產生 har 默認值 接受 上傳文件 tle 1、文件上傳原理   將客戶端的文件上傳到服務器,再將服務器的臨時文件上傳到指定目錄 2、客戶端配置 提交表單 表單的發送方式為post 添加enctype="multipart/form-data"

Linux基本常用命令之lsdate,cal

Linux基礎【1】顯示日期的指令:date示例:(1)#date +%Y/%m/%d結果:2018/02/27(2)#date +%H:%M結果:10:48【2】顯示日歷的指令:cal格式:cal [month] [year]示例:(1)#cal 2 2018(2)#cal 13 2018結果:cal:il

Spring Boot中使用MyBatis註解配置1

sql type .org 實體 sch 整合 PE 匯總 同傳 之前在Spring Boot中整合MyBatis時,采用了註解的配置方式,相信很多人還是比較喜歡這種優雅的方式的,也收到不少讀者朋友的反饋和問題,主要集中於針對各種場景下註解如何使用,下面就對幾種常見的情況舉

NGINX源碼安裝配置./configure,最全解析

unzip roo without rpc服務 所有 googl 版本 並且 大文件 NGINX ./configure詳解 在"./configure"配置中,"--with"表示啟用模塊,也就是說這些模塊在編譯時不會自動構建&qu

logback logback.xml常用配置<configuration> and <logger>

配置文件 cti 原創文章 分類 lis ali 配置 默認值 原創 摘自:http://aub.iteye.com/blog/1101260logback logback.xml常用配置詳解(一)<configuration> and <logger&

mybatis 代碼生成器IDEA, Maven)及配置部分配置你應該不知道

win 項目 找到 mini 屬性 新建 ini 默認 sub 在使用 mybatis 過程中, 當手寫 JavaBean和XML 寫的越來越多的時候, 就越來越同意出錯。這種重復性的工作, 我們當然不希望做那麽多。 還好, mybatis 為我們提供了強大的代碼生成--M

快速安裝Nginx及配置未完待續

導讀: Nginx (engine x) 是一個高效能的HTTP和反向代理伺服器,也是一個IMAP/POP3/SMTP伺服器,從2007年被德國人開發出來後可以說在市場的佔有率一路飆升,因為它支援高併發,而且還能阻止dos攻擊,它是當前較具影響力的一個http伺服器軟體,像百度等大廠都使用它,所以這是作為一