webpack4.0入門配置檔案
wepback風頭正火 ,但是公司一直在用gulp,正好趕上年底活動,藉此機會第一次嘗試了webpack,說實話webpack真的很強大,內容一層一層遞進。
這幾天跟著官網跑了一遍,然後寫了自己的配置檔案,因為活動內容不多,很多強大的功能沒有用上,但是相信對於入門來說足夠了。
下面來總結並附上原始碼
當 webpack 處理應用程式時,它會遞迴地構建一個依賴關係圖,其中包含應用程式需要的每個模組,然後將所有這些模組打包成一個或多個 bundle。
webpack支援的模組語法有哪些?
ES6,CommonJs,Amd
webpack和gulp的區別?
Webpack可以通過眾多loader和plugin完成許多gulp上的功能,但Webpack本質在於模組打包,而gulp的本質在於執行任務;使用webpack-stream包可以實現gulp和webpack的搭配使用
核心概念
1.入口:指定使用哪個模組來作為構建內部依賴圖的開始,隨後打包成bundle
2.輸出:定義輸出生產的bundle的位置及檔名;
3.loader:讓webpack可以處理非js模組;loader 可以將所有型別的檔案轉換為webpack 能夠處理的有效模組。
4. 外掛:執行的任務範圍包括從打包優化和壓縮,一直到重新定義環境中的變數,目的在於完成一些loader無法完成的任務。
常用配置項
1.mode: ‘development’|| ‘production’ || ‘none’
2.entry: array || obj
3.output: {
path: path.resolve(__dirname, "dist"), // 輸出檔案的目標路徑
filename:’bundle.js’,// 打包後的檔名
publicPath: ‘static’// 輸出解析檔案目錄,url相對於html
}
4.module: {
rules: [
{
test: /\.js$/, // 指定使用此loader的檔案
use: ‘babel-loader’,
options: { },
include: /src/, // 匹配項
exclude: /node_modules/ // 非匹配項
}
]
}
5.plugins: […instance]
6.devServer: {
host: ‘localhost’,
port: ‘8080’,
contentBase: Boolean|| string || array, // 伺服器從哪裡獲取內容
hot:boolean, // 是否開啟webpack模組熱替換
open: Boolean, // 是否自動開啟瀏覽器
proxy: { path: targetUrl}, // 代理
…others
}
7.resolve: {
alias: {
test: url
},
extensions: [.js, .json]
}
8.devtool: string || false
可選值:
cheap-eval-source-map
eval-source-map
cheap-source-map
source-map
cheap-module-eval-source-map
…others
常用loader及plugin
loader
Css-loader:解析css中資源路徑;
Sass-loader:sass轉碼為css
Postcss-loader:使webpack可以用postcss處理css
Px2rem-loader: px轉換為rem
Style-loader:將css以style標籤的形式插入到dom中
Babel-loader:轉碼js以提高相容性
url-loader:圖片轉base64
webpack imagemin-webpack-plugin 壓縮圖片
file-loader:將檔案輸出到輸出目錄並返回檔案路徑
html-loader:處理html中資源路徑
eslint-loader:使js支援eslint
plugin
html-webpack-plugin:根據模板匯出html檔案,並注入bundle
DinePlugin: 建立編譯時可以進行配置的全域性變數。
HashedModuleIdsPlugin: 根據模組的相對路徑生成一個四位數的hash作為模組id
extract-text-webpack-plugin:分離css
mini-css-extract-plugin:分離css
uglifyjs-webpack-plugin:壓縮js
optimize-css-assets-webpack-plugin:壓縮css
clean-webpack-plugin: 清空某個目錄
cli常用命令
--config 使用指定的配置檔案
--env.key=value 指定環境變數
--mode=production 指定模式
--progress 列印編譯進度的百分比
--display-error-details 展示錯誤細節
--define 定義環境變數
-w 觀察檔案變化,變化後重新執行構建流程
--hot 開啟模組熱替換
--json > stats.json 將編譯結果的各種資訊輸出為json檔案
--profile
捕獲編譯時每個步驟的時間資訊
配置檔案編寫
前端常見需求:
1) Js壓縮
2) Css壓縮
3) Css提取
4) 小圖片轉base64
5) Px轉rem
6) Css字首新增
7) Sass轉碼
8) Babel轉碼
9) 檔名加hash
10) 檔案編碼格式轉換(常見utf-8與gbk互轉)
11) 程式碼分離
12) Eslint
13) 模組熱替換
14) 配置編譯過程的全域性變數
15) 打包後的程式碼注入html中
1. 常用模組變數
__dirname:當前資料夾路徑
2. 常用佔位符
[hash]:模組識別符號的hash(後拼接:‘:n’可指定長度)
[chunkhash]: chunk內容的hash(後拼接:‘:n’可指定長度)
[name]:模組名稱
[id]: 模組識別符號
3. 配置檔案使用commonjs編寫的,配置型別有下面幾種:
1) 匯出一個配置物件
2) 匯出一個函式
3) 匯出一個promise
程式碼分離
該功能可以把程式碼分離到不同的 bundle 中,然後可以按需載入或並行載入這些檔案。程式碼分離可以用於獲取更小的 bundle,以及控制資源載入優先順序,如果使用合理,會極大影響載入時間。
程式碼分離的方式:
1.手動配置多個入口檔案
2.使用webpack自帶的splitChunks功能
3.使用import()動態匯入
下面附上自己的web.config.js
//生成html檔案 npm i -D html-webpack-plugin const HtmlWebpackPlugin = require('html-webpack-plugin'); //每次打包前清理目錄檔案 npm i -D clean-webpack-plugin const CleanWebpackPlugin = require('clean-webpack-plugin'); //js壓縮 npm i -D uglifyjs-webpack-plugin const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //單獨打包css,webpack3是利用extract-text-webpack-plugin外掛提取單獨打包css檔案 //webpack4得使用mini-css-extract-plugin npm i -D mini-css-extract-plugin const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //壓縮css npm i -D optimize-css-assets-webpack-plugin const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //用於打包後的檔案轉碼 npm i webpack-encoding-plugin const EncodingPlugin = require("webpack-encoding-plugin"); //提取公共模組 請參考https://segmentfault.com/a/1190000012828879 //引入glob正則匹配多頁面 npm i -D glob var glob = require('glob'); //安裝webpack npm i -D [email protected]<version>(版本號) //webpack4後將webpack-cli分別出來要自己安裝 npm in -D webpack-cli const webpack = require('webpack'); //處理檔案路徑的工具 const path = require('path'); //設定變數判斷是開發環境還是生產環境 npm i -D cross-env const devMode = process.env.NODE_ENV !== 'production'; //獲取所有路口js,生成一個路徑物件. var getEntry = function () { var entry = {}; //首先我們先讀取我們的開發目錄 glob.sync('./source/**/*.js').forEach(function (name) { var n = name.slice(name.lastIndexOf('source/') + 7, name.length - 3); n = n.slice(0, n.lastIndexOf('/')); //接著對路徑字串進行了一些裁剪成想要的路徑 entry[n] = name; }); console.log(entry); /** * entry = { * 'crowd/index' : './source/main/index/index.js', * 'index/index' : './source/content/index/index.js' * } * **/ //最後返回entry 給 webpack的entry return entry; }; module.exports = { entry: getEntry(), //入口檔案 output: { //檔案輸出位置 path: path.resolve(__dirname, 'dist'), //配置輸出路徑 filename: "js/[name].bundle.js", //檔案輸出形式 chunkFilename: "js/[name].chunk.js", publicPath: '/'//虛擬目錄,自動指向path編譯目錄 }, //tips:chunkFilename網上覺得靠譜的解釋 //chunkname是未被列在entry中,卻又需要被打包出來的檔案命名配置。什麼場景需要呢?在按需載入(非同步)模組的時候, //這樣的檔案是沒有被列在entry中的,如使用CommonJS的方式非同步載入模組: // require.ensure(["modules/tips.jsx"], function(require) { // var a = require("modules/tips.jsx"); // // ... // }, 'tips');//tips:一般來說,引入第三方庫有一下三種情況: // 通過CDN引入; // 通過npm 安裝並引入; // 第三方js檔案就在本地 resolve: {//一些配置項,如第三方的js檔案就在本地,怎麼通過webpack引入 alias: { $: path.resolve(__dirname, './dist/jquery.js'), jQuery: path.resolve(__dirname, './dist/jquery.js'), } }, plugins: [ //外掛 require("autoprefixer"),//引入自動補全字首,直接引入autoprefixer-loader並沒有生效, //安裝postcss-loader並引入autoprefixer時生效,並建立postcss.config.js檔案 new webpack.HotModuleReplacementPlugin(),//啟動模組熱替換 new webpack.NamedModulesPlugin(), //用於啟動HMR時可以顯示模組的相對路徑 new UglifyJsPlugin({}),//js壓縮 new MiniCssExtractPlugin({//css分離 filename: devMode ? 'css/[name].css' : 'css/[name].[hash:5].css', chunkFilename: devMode ? 'css/[id].css' : 'css/[id].[hash:5].css', }), new OptimizeCSSAssetsPlugin({}),//css壓縮 //多頁應用時配置多個html時,那麼就需要例項化該外掛多次 new HtmlWebpackPlugin({ template: 'src/html/index.html', excludeChunks: ['list', 'detail']//配置不允許注入的chunk }), new HtmlWebpackPlugin({ filename: 'list.html', template: 'src/html/list.html', chunks: ['common', 'list']//允許插入到模板中的一些chunk,不配置此項預設會將entry中所有的chunk注入到模板中 }), new HtmlWebpackPlugin({ filename: 'detail.html', template: 'src/html/detail.html', chunks: ['common', 'detail'] }), //用來專案的轉碼 new EncodingPlugin({ encoding: 'GB2312' }), //清除dist資料夾 new CleanWebpackPlugin(['dist']) ], //模組 module: { rules: [ { test: /\.js$/, use: [ { loader: 'babel-loader',//cnpm i -D babel-loader @babel/core @babel/preset-env webpack options: {//npm i -S babel-polyfill 實現瀏覽器對不支援API的相容(相容舊環境、填補) presets: ['@babel/preset-env'] } } ], exclude: /node_modules/ }, { test: /\.(sa|sc|c)ss$/, use: [//npm i -D style-loader css-loader devMode ? 'style-loader' : MiniCssExtractPlugin.loader,//因為MiniCssExtractPlugin不支援熱替換,所以當是生產環境時不啟用這個外掛 'css-loader', 'postcss-loader',//npm i -D postcss-loader // {網上還有這種寫法 // loader: 'postcss-loader', // options: { // plugins: () => [ // require('autoprefixer') // ], // } // }, 'sass-loader',//使用sass-loader要使用node-loader,npm i -D sass-loader node-sass { loader: 'px2rem-loader',//配合flexible實現移動端下的適配 npm i px2rem-loader // options here options: { remUni: 75, remPrecision: 8 } } ] }, { test: /\.(jpg|png|gif|jpeg)$/, use: [ {//npm i -D url-loader loader: 'url-loader',// 在檔案大小(單位 byte)低於指定的限制時,可以返回一個 DataURL。 options: { limit: 10000,//設定位元組限制 name: 'img/[name]_[hash:5].[ext]' } } ] } ] }, //配置開發服務功能 npm i -D webpack-dev-server devServer: { contentBase: path.resolve(__dirname, 'dist'), historyApiFallback: true, hot: true, port: 9000, publicPath:'/', } };