webpack 從開始到結束

Link-X發表於2018-11-16

教你從零開始寫一個簡單的webpack打包配置

這篇文章的全部程式碼已經上傳到github。有需要的童鞋可以去看看。
github.com/Link-X/webp… 先簡單看一下我們這個教程最終的檔案結構

webpack 從開始到結束
主要就是這個webpack.config.prod.js 和 webpack.config.js。這兩是全部的webpack配置

正文開始-------

千里之行始於足下。首先我們先新建一個資料夾,簡單點就叫pack吧

開啟這個資料夾,此時資料夾裡什麼都沒有

webpack 從開始到結束

第一步:需要一個 package.json的檔案。

我們通過yarn init(npm init也行) 命令列初始化一個。

如果你沒有按照yarn或者npm的話去先去安裝一個。這裡就不細說了,這裡推薦yarn。
1、npm安裝方式:直接下載一個node,它自帶npm。。
2、yarn安裝方式:yarn安裝教程點這個教程很詳細。

安裝完後輸入 yarn init 不出意料會出現這些東西,專案名稱、版本、說明、協議、儲存地址等等

webpack 從開始到結束
一步步確認下來後,pack資料夾就會出現一個 package.json的檔案
webpack 從開始到結束
開啟這個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。然後通過它會知道哪些是開發依賴,哪些是生產依賴。當然還有很多別的。這裡只是簡單介紹一下

webpack 從開始到結束
開啟 package.json,發現裡面多了一個devDependencies, 剛剛我們add的哪兩個開發依賴就在這裡。

webpack 從開始到結束
細心的同學可能已經發現,檔案裡還多了一個 node_modules的資料夾。開啟一看,發現裡面多了一大堆亂七八糟的東西。電腦配置不高的童靴光是把它刪除就可能就要卡一兩分鐘,當然你千萬別測試電腦效能刪了它(ememem~~!)。

webpack 從開始到結束

為什麼這個檔案這麼大膩,我們們只是安裝了兩個外掛而已。這因為我們安裝的這兩個東西它也有他自己的依賴。它的依賴又可能依賴了別的依賴。如此迴圈~~ 啊哈哈。

webpack 從開始到結束
這只是一個簡單的解釋。它裡面還有一些特殊的資料夾。比如.bin 這是存放一些命令的檔案。

說到這個.bin 那麼,童靴們接下來我們要搞一些事情。
首先在pack資料夾下,我們新建一個 src檔案。在src檔案下又新建一個 index.js,裡面什麼都不寫
再開啟剛剛生成的package.json。在裡面新增一條資料。

"scripts": {
    "build": "webpack --mode production"
 }
複製程式碼

webpack 從開始到結束
然後,在控制檯執行 yarn build

webpack 從開始到結束

臥槽什麼情況。沒錯,是的此時以你已經精通webpack。變身 webpack 配置大失。

webpack 從開始到結束

是不是很簡單。啊哈哈哈~~~。就是這麼簡單!

webpack 從開始到結束

嘿嘿,好啦,其實這只是一個開始,剛剛說到.bin資料夾,解釋一下我們新增的再package.json 裡的 scripts,裡面的命令 就是在執行的時候自動新建一個 Shell,在這個 Shell 裡面執行指定的指令碼命令,比如 yarn build,會將當前目錄的node_modules/.bin子目錄加入PATH變數,執行結束後,再將PATH變數恢復原樣。

第三步: 自定義配置webpack 配置

剛剛的操作並不能完成我們日常的需求,接下來我教大家如何,自定義配置webpack。首先我們新建一個 webpack.config.js 檔案

webpack 從開始到結束

當我們執行打包命令的時候,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 檔案

webpack 從開始到結束
裡面寫

{
    "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

webpack 從開始到結束
打包成功. 開啟dist/index.html

webpack 從開始到結束
沒錯熟悉的味道.

然後是熱更新,這塊我也不是很熟悉。簡單貼一下配置吧,

pack下新建一個config資料夾,然後新建一個server.js

webpack 從開始到結束

裡面寫

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/

webpack 從開始到結束
成功,隨便修改src/index.js 下任意程式碼就可以看到也沒自動重新整理了

相關文章