天天看點

webpack4.x的常用配置項分析

// webpack 是基于nodejs的 
// npx webpack 建構
// webpack的配置是對象 執行建構會找webpack.config.js這個配置檔案
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 清除打封包件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require("webpack"); // 自帶熱子產品替換

module.exports = {
    // 上下文 項目打包的相對路徑 必須是絕對路徑  一般是不會更改的
    // context: process.cwd(),
    // 單入口 執行建構的入口 項目入口  單檔案是字元串 多檔案是數組 ['xx.js','xxxx.js']
    entry: './src/index.js',
    // 多入口 entry 對象形式并且是多鍵值 對應多出口 output的 filename: '[name].js' 占位符,
    // entry: {
    //     aa: 'aa.js',
    //     bb: 'bb.js'
    // },
    // 出口
    output: {
        // 建構的檔案資源放在那裡? 必須是絕對路徑
        path: path.resolve(__dirname, './dist'),
        // 建構出來的檔案資源叫啥?
        // filename: 'main.js',
        filename: '[name]-[hash:6].js', // 6代表6位最長20位 hash的目的是緩存
        // filename: '[name]-[chunkhash:6].js', // 6代表6位最長20位 一般是多入口 各自改動不會互相影響
        // publicPath: '//xxx.com', //指定存放 JS⽂件的 CDN位址 不會自動上傳 cdn
    },
    // 常見占位符 
    //hash 
    //name[字元串的key 預設是main] 
    //chunkhash 根據不同入口entry進行依賴解析,建構對應的chunk,生成對應的xx,隻要entry的子產品麼沒有内容改變hash不變
    //id 
    // 配置模式  none development production' 生産環境會壓縮 如果沒有設定預設是 production
    mode: "development",
    // 處理不認識的子產品
    module: {
        // loader 子產品轉換
        // 規則
        rules: [
            {
                test: /\.css$/,
                include: path.resolve(__dirname, "./src"), // loader優化項 include指定檔案夾查找  exclude 排除某個檔案夾下
                // loader的執行順序是從後往前 css-loader加到js子產品中去 css in js方式
                // style-loader從js中提取css的loader在html中建立
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" },
                    { loader: "postcss-loader" }
                ]
            },
            {
                test: /\.less$/,
                include: path.resolve(__dirname, "./src"), // 制定檔案查找
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader", // translates CSS into CommonJS
                    options: {
                        modules: true
                    }
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }, { loader: "postcss-loader" }]
            },
            // 處理圖檔 ext 什麼字尾名就是輸出什麼
            {
                test: /\.(png|jpg|gif)$/,
                include: path.resolve(__dirname, "./src"), // 制定檔案查找
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:6].[ext]',
                            publicPath: 'assets/',
                            outputPath: 'images/'  // dist下面的目錄下面
                        }
                    }
                ]
            },
            // 推薦 url-loader 因為它包含了 file-loader的所有功能 還支援 limit限定檔案大小
            {
                test: /\.(png|jpg|gif)$/,
                include: path.resolve(__dirname, "./src"), // 制定檔案查找
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            outputPath: 'images/',  // dist下面的目錄下面 下面這個打包後混合在打包後的js裡面了
                            // 推薦小體積圖檔轉成 base64 1024 = 1kb
                            limit: 12 * 1024
                        }
                    }
                ]
            },
            {
                test: /\.js$/,
                include: path.resolve(__dirname, "./src"), // 制定檔案查找
                exclude: /node_modules/, // 排除 node_modules下面
                use: {
                    loader: "babel-loader",
                    // options可不在這邊配置 項目根目錄建立 .babelrc 檔案丢進去即可 
                    options: {
                        presets: [
                            [
                                "@babel/preset-env",
                                {
                                    targets: {
                                        edge: "17",
                                        firefox: "60",
                                        chrome: "67",
                                        safari: "11.1"
                                    },
                                    corejs: 2, //新版本需要指定核⼼庫版本
                                    useBuiltIns: "entry" //按需注⼊
                                }
                            ],
                            "@babel/preset-react", // 對jsx的支援
                        ]
                    }
                }
            },
        ]
    },
    // 配置子產品解析
    resolve: {
        // 第三方依賴 node_modules 這裡去查找
        modules: [path.resolve(__dirname, './node_modules')],
        // 别名 減少查找過程 起别名
        alias: {
            "@": path.resolve(__dirname, "./src/css"),
            react: path.resolve(
                __dirname,
                "./node_modules/react/umd/react.production.min.js"
            ),
            "react-dom": path.resolve(
                __dirname,
                "./node_modules/react-dom/umd/react-dom.production.min.js"
            )
        },
        // 去除字尾 不建議濫用最好帶上字尾 減少查找時間
        extensions:['.js','.json','.jsx','.ts'],
    },
    // 配置這個cdn 的不需要打包到 bundle⽂件
    externals: {
        // jquery通過script引⼊之後,全局中即有了 $ 變量
        // 'jquery': '$',
        // 'loadsh': '_'
    },
    // 推薦配置
    // devtool:"cheap-module-eval-source-map",// 開發環境配置
    // devtool:"cheap-module-source-map", // 線上⽣成配置
    // 測試配置
    devtool: "none", // 把source-map 關閉 或者把 mode 設定為 production   設定為 source-map dist下會多一個map檔案
    // webpack-dev-server的配置
    devServer: {
        hot: true, // 熱子產品替換配置
        //即便HMR沒有生效,浏覽器也不要自動重新整理。
        hotOnly: true,
        contentBase: path.join(__dirname, "dist"),
        compress: true,
        open: true, // 自動打開浏覽器
        port: 9000, // 端口
        // 代理 改了配置檔案首先需要重新開機服務
        proxy: {
            "/api": {
                target: "http://localhost:9092"
            }
        },
        // 自帶了express服務 mock server
        before(app, server) {
            app.get('/api/info', (req, res) => {
                res.json({
                    name: 'express傳回結果',
                    age: 22,
                    msg: '歡迎來到express課程'
                })
            })
        }
    },
    // 插件
    plugins: [
        // webpack的output.path目錄中的所有檔案将被删除一次,但是目錄本身不會。
        // 如果使用webpack 4+的預設配置,<PROJECT_DIR> / dist /下的所有内容都将被删除
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: "首頁",
            template: "./src/index.html",
            filename: "index.html",
            minify: {}, // 針對開發和生産壓縮代碼
        }),
        new webpack.HotModuleReplacementPlugin(),
    ]
}