從零開始配置webpack(基於webpack 4 和 babel 7版本)

劉小夕發表於2019-03-22

webpack 核心概念:

  • Entry: 入口
  • Module:模組,webpack中一切皆是模組
  • Chunk:程式碼庫,一個chunk由十多個模組組合而成,用於程式碼合併與分割
  • Loader:模組轉換器,用於把模組原內容按照需求轉換成新內容
  • Plugin:擴充套件外掛,在webpack構建流程中的特定時機注入擴充套件邏輯來改變構建結果或做你想要做的事情
  • Output: 輸出結果

webpack流程:

webpack啟動後會從 Entry 裡配置的 Module 開始遞迴解析 Entry 依賴的所有Module.每找到一個Module,就會根據配置的Loader去找出對應的轉換規則,對Module進行轉換後,再解析出當前的Module依賴的Module.這些模組會以Entry為單位進行分組,一個Entry和其所有依賴的Module被分到一個組也就是一個Chunk。最好Webpack會把所有Chunk轉換成檔案輸出。在整個流程中Webpack會在恰當的時機執行Plugin裡定義的邏輯。

下面我們開始從零開始配置一個支援打包圖片,CSS,LESS,SASS,支援ES6/ES7和JSX語法,並對程式碼進行壓縮的webpack配置.

更多文章可戳: github.com/YvetteLau/B…

1. 最簡webpack配置

首先初始化npm和安裝webpack的依賴:

npm init -y
npm install --save-dev webpack webpack-cli
複製程式碼

配置 webpack.config.js 檔案如下:

const path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'src/index.js'),
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    }
}
複製程式碼

說明: publicPath 上線時配置的是cdn的地址。

使用命令進行打包:

webpack --mode production
複製程式碼

也可以將其配置到 package.json 中的 scripts 欄位.

入口檔案為 src/index.js, 打包輸出到 dist/bundle.js.

2. 使用模板 html

html-webpack-plugin 可以指定template模板檔案,將會在output目錄下,生成html檔案,並引入打包後的js.

安裝依賴:

npm install --save-dev html-webpack-plugin
複製程式碼

在 webpack.config.js 增加 plugins 配置:

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //...other code
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html')
        })
    ]
}
複製程式碼

HtmlWebpackPlugin 還有一些其它的引數,如title(html的title),minify(是否要壓縮),filename(dist中生成的html的檔名)等

3. 配置 webpack-dev-server

webpack-dev-server提供了一個簡單的Web伺服器和實時熱更新的能力

安裝依賴:

npm install --save-dev webpack-dev-server
複製程式碼

在 webpack.config.js 增加 devServer 配置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //...other code
    devServer: {
        contentBase: './dist',
        port: '8080',
        host: 'localhost'
    }
}
複製程式碼

在 package.json 的 scripts 欄位中增加:

webpack-dev-server --mode development
複製程式碼

之後,我們就可以通過 npm run dev , 來啟動服務。

更多 webpack-dev-server 的知識,請訪問: webpack.js.org/configurati…

4. 支援載入css檔案

通過使用不同的 style-loader 和 css-loader, 可以將 css 檔案轉換成JS檔案型別。

安裝依賴:

npm install --save-dev style-loader css-loader
複製程式碼

在 webpack.config.js 中增加 loader 的配置。

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.css/,
                use: ['style-loader', 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            }
        ]
    }
}
複製程式碼

loader 可以配置以下引數:

  • test: 匹配處理檔案的副檔名的正規表示式
  • use: loader名稱
  • include/exclude: 手動指定必須處理的資料夾或遮蔽不需要處理的資料夾
  • query: 為loader提供額外的設定選項

如果需要給loader傳參,那麼可以使用use+loader的方式,如:

module.exports = {
    //other code
    module: {
        rules: [
            {
            use: [{
                        loader: 'style-loader',
                        options: {
                            insertAt: 'top'
                        }
                    },
                    'css-loader'
                ],
                //....
            }
        ]
    }
} 
複製程式碼

5. 支援載入圖片

  • file-loader: 解決CSS等檔案中的引入圖片路徑問題
  • url-loader: 當圖片小於limit的時候會把圖片Base64編碼,大於limit引數的時候還是使用file-loader進行拷貝

如果希望圖片存放在單獨的目錄下,那麼需要指定outputPath

安裝依賴:

npm install --save-dev url-loader file-loader
複製程式碼

在 webpack.config.js 中增加 loader 的配置(增加在 module.rules 的陣列中)。

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192,
                            outputPath: 'images'
                        }
                    }
                ]
            }
        ]
    }
} 
複製程式碼

6.支援編譯less和sass

有些前端同事可能習慣於使用less或者是sass編寫css,那麼也需要在 webpack 中進行配置。

安裝對應的依賴:

npm install --save-dev less less-loader
npm install --save-dev node-sass sass-loader
複製程式碼

在 webpack.config.js 中增加 loader 的配置(module.rules 陣列中)。

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.less/,
                use: ['style-loader', 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: ['style-loader', 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            }
        ]
    }
}        
複製程式碼

7.支援轉義 ES6/ES7/JSX

ES6/ES7/JSX 轉義需要 Babel 的依賴,支援裝飾器。

npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread
複製程式碼

在 webpack.config.js 中增加 loader 的配置(module.rules 陣列中)。

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/react'],
                            plugins: [
                                ["@babel/plugin-proposal-decorators", { "legacy": true }]
                            ]
                        }
                    }
                ],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            },
        ]
    }
}
複製程式碼

8.壓縮JS檔案

安裝依賴:

npm install --save-dev uglifyjs-webpack-plugin
複製程式碼

在 webpack.config.js 中增加 optimization 的配置

const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    //other code
    optimization: {
        minimizer: [
            new UglifyWebpackPlugin({
                parallel: 4
            })
        ]
    }
}

複製程式碼

9.分離CSS(如果CSS檔案較大的話)

因為CSS的下載和JS可以並行,當一個HTML檔案很大的時候,可以把CSS單獨提取出來載入

npm install --save-dev mini-css-extract-plugin
複製程式碼

在 webpack.config.js 中增加 plugins 的配置,並且將 'style-loader' 修改為 { loader: MiniCssExtractPlugin.loader}。

CSS打包在單獨目錄,那麼配置filename。

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.css/,
                use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.less/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ]
}
複製程式碼

10.壓縮CSS檔案

安裝依賴:

npm install --save-dev optimize-css-assets-webpack-plugin
複製程式碼

在 webpack.config.js 中的 optimization 中增加配置

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    //other code
    optimization: {
        minimizer: [
            new OptimizeCssAssetsWebpackPlugin()
        ]
    }
}

複製程式碼

11.打包前先清空輸出目錄

npm install --save-dev clean-webpack-plugin
複製程式碼

在 webpack.config.js 中增加 plugins 的配置

const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    //other code
    plugins: [
        new CleanWebpackPlugin()
    ]
}
複製程式碼

至此,webpack配置已經基本能滿足需求。

完整webpack.config.js和package.json檔案

webpack.config.js檔案:

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
    entry: path.resolve(__dirname, 'src/index.js'),
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    devServer: {
        contentBase: './dist',
        port: '8080',
        host: 'localhost'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/react'],
                            plugins: [
                                ["@babel/plugin-proposal-decorators", { "legacy": true }]
                            ]
                        }
                    }
                ],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            },
            {
                test: /\.css/,
                use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.less/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            outputPath: 'images'
                        }
                    }
                ]
            }
        ]
    },
    optimization: {
        minimizer: [
            new UglifyWebpackPlugin({
                parallel: 4
            }),
            new OptimizeCssAssetsWebpackPlugin()
        ]
    },
    plugins: [
        new htmlWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html'),
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        }),
        new CleanWebpackPlugin()
    ]
}
複製程式碼

package.json檔案:

{
  "name": "webpk",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-decorators": "^7.4.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
    "@babel/preset-env": "^7.4.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "clean-webpack-plugin": "^2.0.1",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.9.0",
    "less-loader": "^4.1.0",
    "mini-css-extract-plugin": "^0.5.0",
    "node-sass": "^4.11.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "uglifyjs-webpack-plugin": "^2.1.2",
    "url-loader": "^1.1.2",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  },
  "dependencies": {
    "react": "^16.8.4",
    "react-dom": "^16.8.4",
    "react-redux": "^6.0.1",
    "redux": "^4.0.1"
  }
}
複製程式碼

更多loader和plugin的引數可以參考: www.webpackjs.com/loaders/ www.webpackjs.com/plugins/

如果你有其它的webpack配置需求,歡迎留言~

從零開始配置webpack(基於webpack 4 和 babel 7版本)

謝謝您花費寶貴的時間閱讀本文,如果本文給了您一點幫助或者是啟發,那麼不要吝嗇你的贊和Star哈,您的肯定是我前進的最大動力。github.com/YvetteLau/B…

感謝指出,增加參考連結

關注公眾號,加入技術交流群

從零開始配置webpack(基於webpack 4 和 babel 7版本)

相關文章