教你從零開始寫一個簡單的webpack打包配置
這篇文章的全部程式碼已經上傳到github。有需要的童鞋可以去看看。
github.com/Link-X/webp…
先簡單看一下我們這個教程最終的檔案結構
正文開始-------
千里之行始於足下。首先我們先新建一個資料夾,簡單點就叫pack吧
開啟這個資料夾,此時資料夾裡什麼都沒有
第一步:需要一個 package.json的檔案。
我們通過yarn init(npm init也行) 命令列初始化一個。
如果你沒有按照yarn或者npm的話去先去安裝一個。這裡就不細說了,這裡推薦yarn。
1、npm安裝方式:直接下載一個node,它自帶npm。。
2、yarn安裝方式:yarn安裝教程點這個教程很詳細。
安裝完後輸入 yarn init 不出意料會出現這些東西,專案名稱、版本、說明、協議、儲存地址等等
一步步確認下來後,pack資料夾就會出現一個 package.json的檔案 開啟這個package.json 這裡面就是我們剛剛輸入的東西。這是一個配置檔案,主要是配置我們專案需要的包的。是一個純json我們先不管管它(^_^)
第二步:安裝依賴,首先安裝這兩個 webpack、webpack-cli
yarn add webpack webpack-cli -D
或者
yarn add webpack -D
yarn add webpack-cli -D
這時有同學會問,這個 yarn add *** -D 是啥意思呀,後面那個-D又是什麼鬼。好 我們簡單解釋一下這條命令,這條命令的意思就是把 webpack、webpack-cli 這兩個第三方外掛新增到開發時依賴。也就是說雖然我們安裝了這兩個包,但是我們只是希望在開發的時候使用它們,生產環境的程式碼可別有它們的身影。-D是--save-dev的簡寫, 意思安裝的包到開發環境依賴。最終webpack 打包的時候會去讀取 package.json。然後通過它會知道哪些是開發依賴,哪些是生產依賴。當然還有很多別的。這裡只是簡單介紹一下
開啟 package.json,發現裡面多了一個devDependencies, 剛剛我們add的哪兩個開發依賴就在這裡。 細心的同學可能已經發現,檔案裡還多了一個 node_modules的資料夾。開啟一看,發現裡面多了一大堆亂七八糟的東西。電腦配置不高的童靴光是把它刪除就可能就要卡一兩分鐘,當然你千萬別測試電腦效能刪了它(ememem~~!)。為什麼這個檔案這麼大膩,我們們只是安裝了兩個外掛而已。這因為我們安裝的這兩個東西它也有他自己的依賴。它的依賴又可能依賴了別的依賴。如此迴圈~~ 啊哈哈。
這只是一個簡單的解釋。它裡面還有一些特殊的資料夾。比如.bin 這是存放一些命令的檔案。說到這個.bin 那麼,童靴們接下來我們要搞一些事情。
首先在pack資料夾下,我們新建一個 src檔案。在src檔案下又新建一個 index.js,裡面什麼都不寫
再開啟剛剛生成的package.json。在裡面新增一條資料。
"scripts": {
"build": "webpack --mode production"
}
複製程式碼
然後,在控制檯執行 yarn build
臥槽什麼情況。沒錯,是的此時以你已經精通webpack。變身 webpack 配置大失。
是不是很簡單。啊哈哈哈~~~。就是這麼簡單!
嘿嘿,好啦,其實這只是一個開始,剛剛說到.bin資料夾,解釋一下我們新增的再package.json 裡的 scripts,裡面的命令
就是在執行的時候自動新建一個 Shell,在這個 Shell 裡面執行指定的指令碼命令,比如 yarn build,會將當前目錄的node_modules/.bin子目錄加入PATH變數,執行結束後,再將PATH變數恢復原樣。
第三步: 自定義配置webpack 配置
剛剛的操作並不能完成我們日常的需求,接下來我教大家如何,自定義配置webpack。首先我們新建一個 webpack.config.js 檔案
當我們執行打包命令的時候,webpack會預設讀取這個檔案。獲取使用者自定義的配置。這個配置檔案本質上是一個node的指令碼,所以靈活性比較高
首先是入口(entry):入口是什麼?webpack 的入口就是 從這個檔案開始,以這裡為起點開始依賴的所以東西全部打包。像一條線把你的程式碼連起來。
// module.exports 是node預設支援的CMD模組語法,我們這裡的意思就是匯出一個字面量物件,讓webpack讀取來當它的配置。詳細可以自行搜尋CMD模組
module.exports = {
// 這是單入口的配置寫法
entry: './src/index.js'
}
module.exports = {
// 這是多入口的寫法
entry: {
foo: './src/top.js',
bar: './src/bottom.js',
// ...
}
}
複製程式碼
然後出口(output):
啥是出口,顧名思義,就是指 webpack 最終構建出來的靜態檔案
// 有童鞋問著個path.resolve(__dirname, 'dist')是啥呀。
// path.resolve() 如果有引數 返回這個引數相對於當前的工作目錄的絕對路徑
// __dirname 這個也是node的一個api,意思是這個被執行的檔案的絕對路徑
// path.resolve(__dirname, 'dist')返回當前工作目錄被執行檔案(webpack.config.js)的絕對路徑的下的dist。
// 總之我們麼這就是返回 pack下dist 在你電腦的絕對路徑
const path = require('path')
module.exports = {
...
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
}
}
複製程式碼
在然後是loader:
啥loader? 剛剛我們說了 webpack會從入口開始把你的程式碼連起來,連起來然後呢?烤了吃?^_^ 當然不是。webpack會通loader 把他們都轉換了。轉換它幹啥?為啥要轉換。我寫的程式碼這麼吊,還需要轉換麼...
開個玩笑,當然要轉換。loader的目的就是轉換你的程式碼,比如 我們知道css 有些屬性還處於實驗階段,需要你加入一個字首瀏覽器才回去識別他們,如 --ms-- --webkit-- 。
還有js 有些新api 特性等 瀏覽器廠商可能還沒實現。咋辦呢,我們麼通過loader 轉換一下就可以把我們自己寫的新程式碼,讓沒有它可以在瀏覽器上執行。
還有less sass 等瀏覽器天生並不能能識別它們。需要一個轉換。
module.exports = {
...
...
module: {
rules: [
{
test: /\.js$/, // 需要轉換的檔案,這裡用正則匹配所以.js檔案
loader: 'babel-loader', // 指定用到的那個loader去轉換
include: [path.resolve(__dirname, 'src')] // 指定loader從哪裡轉換檔案
}
]
},
}
複製程式碼
對了,這個 babel-loader 還需要一個單獨的配置檔案。別方,我們簡單配置一下即可。 pack 目錄下新建一個 .babelrc 檔案
裡面寫{
"presets": ["es2015", "stage-2"],
"plugins": []
}
複製程式碼
babel-loader 是個第三方外掛,我們需要安裝一下,只需要在開發環境依賴即可
yarn add babel-loader babel-cli babel-preset-es2015 babel-preset-stage-2 -D
然後是plugins:
plugins 是啥?plugins 就是除了loader之外的所以事,都是plugins做,比如壓縮程式碼什麼的。
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
...
...
plugins: [
new UglifyPlugin(), // 壓縮檔案
new HtmlWebpackPlugin({
filename: 'index.html', // 配置輸出檔名和路徑
minify: { // 壓縮 HTML 的配置
minifyJS: true // 壓縮 HTML 中出現的 JS 程式碼
}
})
]
}
複製程式碼
這裡我們也需要安裝一下uglifyjs-webpack-plugin 、 html-webpack-plugin ,兩個分別是壓縮檔案的,和幫我們生成一個index.html的,兩個都是開發依賴
yarn add uglifyjs-webpack-plugin -D
yarn add html-webpack-plugin -D
最後我們再說一個resolve 配置:
module.exports = {
...
...
...
...
resolve: {
extensions: [".wasm", ".mjs", ".js", ".json"], // 查詢檔案順序
alias: {
"@": path.resolve(__dirname, 'src') // 路徑別名,以後匯入模組,前面加一個@就是當如src下的xxx
}
}
}
複製程式碼
引入的時候有時候我們會省略字尾,不如後面那個.js .html 這個 extensions 就是配置webpack 用那個字尾優先查詢檔案. alias 的意思就是配置一個路徑別名,用過vue的人應該比較熟悉這個。 如
import test from '@/test/index.js'
複製程式碼
就是匯入當前目錄src下的test/index.js
在提一下通過es6或者cmd 模組引入一個模組,首先會去找是否當前目錄,當前沒目錄沒有會去找上級,最後到根目錄,如果還是沒有就會找node_module 。要是還是沒找到就報錯.
最後我們的完整配置就是
// webpack.config.js
const path = require('path')
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [{
test: /\.js$/, // 用 babel-loader 解析js
loader: 'babel-loader',
include: [path.resolve(__dirname, 'dist')]
}]
},
plugins: [
new UglifyPlugin(), // 壓縮檔案
new HtmlWebpackPlugin({
filename: 'index.html', // 配置輸出檔名和路徑
minify: { // 壓縮 HTML 的配置
minifyJS: true // 壓縮 HTML 中出現的 JS 程式碼
}
})
],
resolve: {
extensions: [".wasm", ".mjs", ".js", ".json"], // 查詢檔案順序
alias: {
"@": path.resolve(__dirname, 'src') // 路徑別名,以後匯入模組,前面加一個@就是當如src下的xxx
}
}
}
複製程式碼
我們在src/index.js下寫一行 console.log(1) 然後執行一下 yarn build
打包成功. 開啟dist/index.html 沒錯熟悉的味道.然後是熱更新,這塊我也不是很熟悉。簡單貼一下配置吧,
pack下新建一個config資料夾,然後新建一個server.js
裡面寫
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require("webpack-hot-middleware")
const webpackOptions = require('../webpack.config.js')
const path = require('path')
webpackOptions.mode = 'development'
const compiler = webpack(webpackOptions),
express = require('express'),
app = express(),
DIST_DIR = path.join(__dirname, '..', 'dist')
const devMiddleware = webpackDevMiddleware(compiler, {
publicPath: webpackOptions.output.publicPath,
quiet: true
})
const hotMiddleware = webpackHotMiddleware(compiler, {
log: false,
heartbeat: 2000
})
app.use(devMiddleware)
app.use(hotMiddleware)
app.listen(3000, () => console.log('http://localhost:3000'))
複製程式碼
然後需要安裝一下三個需要用的的熱更新的外掛
yarn add webpack-dev-middleware webpack-hot-middleware express -D
在webpack.config.js 改三個小小的地方.
// 1、新增匯入 webpack
const webpack = require('webpack')
// 2、入口改成這樣
entry: {
main: ['webpack-hot-middleware/client.js?reload=true', './src/index.js']
}
// 3、plugins 改成這樣
plugins: [
new UglifyPlugin(), // 壓縮檔案
new HtmlWebpackPlugin({
filename: 'index.html', // 配置輸出檔名和路徑
minify: { // 壓縮 HTML 的配置
minifyJS: true // 壓縮 HTML 中出現的 JS 程式碼
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
//
複製程式碼
最後在 package.json 的scripts 加入"start": "node config/server.js"
// 如下
{
"name": "packTest",
"version": "0.01",
"description": "webpack初體驗",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "node config/server.js",
"build": "webpack --mode production"
},
"devDependencies": {
"babel-loader": "^8.0.4",
"express": "^4.16.4",
"html-webpack-plugin": "^3.2.0",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.4.0",
"webpack-hot-middleware": "^2.24.3"
}
}
複製程式碼
yarn start .啟動啦 訪問 http://localhost:3000/
成功,隨便修改src/index.js 下任意程式碼就可以看到也沒自動重新整理了