摘要:由于這種差異我們將對預處理器文件的配置封裝為函數,由參數生成對應配置,將文件放入文件內,將配置放在文件內。
前言
源代碼
熟悉 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" }
需要注意的有:
文件名 hashhash 是用在文件輸出的名字中的,如 [name].[hash].js,總的來說,webpack 提供了三種 hash:
[hash]:此次打包的所有內容的 hash。
[chunkhash]:每一個 chunk 都根據自身的內容計算而來。
[contenthash]:由 css 提取插件提供,根據自身內容計算得來。
三種 hash 的使用,我們在優化部分再講,先優先使用 [chunkhash]。
loader 優先級loader 優先級需要注意兩點,
同 test 配置內優先級:在同一個 test 下配置多個 loader ,優先處理的 loader 放在配置數組的后面,如對 less 處理,則:
{ test: /.less$/, use: [ "style-loader", "css-loader", "postcss-loader", "less-loader" ] }
不同 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)為例:
less-loader 先處理 less 語法
postcss-loader 進行前綴添加等其他處理
css-loader 將內容引入 @import 所在的 css 文件內
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: ["http:// xxx-loaders"], scss: ["http:// 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-loaderpostcss-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 ,有三個預設值:development,production,none,我們在生產模式選用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 文件發生關聯。
需要我們手動添加(還可能包括后面提取出來的 css 文件)到 HTML 文件。
我們可以使用 html-webpack-plugin 插件自動完成這個工作。
當僅使用 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 這兒的多行注釋渲染有點問題
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107725.html
摘要:今天就嘗試著一起來聊聊吧,旨在幫大家加深理解新手更容易上路,都能從到搭建配置自定屬于自己的腳手架,或對已封裝好的腳手架有進一步的鞏固,接下來蘇南會詳細講解中的每一個配置字段的作用部分為新增。 showImg(https://segmentfault.com/img/bVbjmMV?w=1008&h=298); 前言 經常會有群友問起webpack、react、redux、甚至cre...
摘要:自從年月份對外公布以來,已經經過了個月的迭代,期間發布了幾十個正式版本,但一直沒有到,因為我們覺得是個里程碑版本,我們必須做的足夠完善才敢稱之為。 自從17年11月份對外公布以來,KPC已經經過了8個月的迭代,期間發布了幾十個正式版本,但一直沒有到1.0,因為我們覺得1.0是個里程碑版本,我們必須做的足夠完善才敢稱之為1.0。而如今我們有信心對外宣布:KPC 1.0終于來了! 其實距離...
摘要:相關的內容為這樣對于一個處理的第二階段也就結束了,通過去攔截不同類型的,并返回新的,跳過后面的的執行,同時在內部會剔除掉,這樣在進入到下一個處理階段的時候,不在使用的范圍之內,因此下一階段便不會經由來處理。 文章首發于個人github blog: Biu-blog,歡迎大家關注~ Webpack 系列文章: Webpack Loader 高手進階(一)Webpack Loader 高手...
摘要:配置規則在文件中添加代碼如下和是中規則的名稱。安裝,命令如下這個插件將會提醒模塊腳本之間模擬瀏覽器共享全局變量的行為,因為這不適用于模塊腳本。而用編譯后的代碼使用這款解析器可以避免不必要的麻煩。 webpack中eslint使用 首先,要使webpack支持eslint,就要要安裝 eslint-loader ,命令如下: npm install --save-dev eslint-l...
閱讀 3054·2021-11-11 16:55
閱讀 3170·2021-10-18 13:34
閱讀 592·2021-10-14 09:42
閱讀 1642·2021-09-03 10:30
閱讀 848·2021-08-05 10:02
閱讀 970·2019-08-30 11:27
閱讀 3484·2019-08-29 15:14
閱讀 1254·2019-08-29 13:02