1. 程式人生 > 實用技巧 >webpack配置打包

webpack配置打包

一、webpack基本安裝

1、建立webpack專案目錄如webpackDemo,並進入webpackDemo;

2、 在node已經安裝的前提下,開啟命令列控制器,輸入如下命令:

npm init -y 
npm install webpack webpack-cli --save-dev  //安裝webpack webpack-cli
(MacOS: sudo npm install webpack webpack-cli -g,sudo npm isntall webpack webpack-cli --save-dev)

命令執行結束後,會生成package.json、package_lock.json、node_modules檔案。然後手動建立src目錄與package.json平級,src目錄下有index.html ,index.js 。

注:npm使用的是淘寶映象,使用命令 npm install --registry=https://registry.npm.taobao.org express (臨時使用);

  (MacOS 如果上面命令不生效,可以使用此命令: npm config set registry https://registry.npm.taobao.org).

二、webpack概念

1、 webpack有四個核心概念:entry(入口) 、output(輸出)、loader、plugin(外掛)。

entry(入口)

告訴webpack構建內部依賴圖開始的模組;可以指定單入口起點檔案或多入口起點檔案。

module.exports = {
    entry:
"./src/index.js" }

output(輸出

告訴webpack輸出建立的bundles,以及如何命名檔案。指定編譯後的輸出檔案路徑。

const OUTPUT_FILE_NAME = "dist"
module.exports = {
    entry:"./src/index.js",
    output: {
        filename: "[name].[contenthash:10].js", //輸出檔名稱, hash解決快取問題
        path: path.resolve(__dirname,'dist') //輸出檔案路徑
    }
}

loader

loader可以讓webpack可以處理非JavaScript檔案,webpack本身只能處理JavaScript。

webpack配置loader有兩個目標:

a). test屬性,用於被對應的loader進行轉換的某個和某些檔案;

b). use屬性,表示進行轉換時,應該使用哪個loader;

module.exports = {
    output: {
        filename: "[name].[contenthash:10].js", //輸出檔名稱, hash解決快取問題
        path: path.resolve(__dirname, OUTPUT_FILE_NAME) //輸出檔案路徑
    },
    module: {
        rules: [{
                //整理html的img資源,
                test: /\.html$/,
                use: ["html-loader"]
            },
            {
                //處理css資源
                test: /\.css$/,
                use: ["css-loader", "style-loader"]
            },
            {
                //處理JS資源
                test: /\.jsx?$/,
                use: ['file-loader']
            }]
    }
}

外掛plugins

loader用於轉換某些型別,外掛用於執行更廣泛的任務。若使用一個外掛,只需require(),然後新增到陣列中。

module.exports = {
    ...,
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            hash: true
        }),
        new MiniCssExtarctPlugin({
            filename: 'css/[name].[contenthash:10].css',
            path: path.resolve(__dirname,'dist')
        })

    ]
}

附全部程式碼:

package.json

{
  "name": "webpack_demo",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "webpack --watch",
    "start": "webpack --config webpack.config.js",
    "build": "webpack --config webpack.config.pro.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtarctPlugin = require("mini-css-extract-plugin"); //將css從js中提取出來

const OUTPUT_FILE_NAME = "dist";
module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "[name].[contenthash:10].js", //輸出檔名稱,hash解決快取問題,具體可見下面的解釋
        path: path.resolve(__dirname, OUTPUT_FILE_NAME) //輸出檔案路徑
    },

    mode: "development", //開發環境,生產環境使用"production"
    module: {
        rules: [{
                //整理html的img資源,
                test: /\.html$/,
                use: ["html-loader"]
            },
            {
                //處理css資源
                test: /\.css$/,
                use: [
                    //將css檔案整合到JS檔案中
                    "css-loader",
                    //建立style標籤,將樣式放入 
                    "style-loader",
                    // css相容性處理:postcss-->postcss-loader postcss-preset-env
                ]
            },
            {
                //處理JS資源
                test: /\.js$/,
                exclude: /node_modules/, //處理除了nodde_modules裡的js檔案
                loader: 'babel-loader' //用babel-loader處理

            },
            {
                //處理圖片資源
                test: /\.(png|svg|jpg|gif)$/,
                use: ['file-loader']
            },
            {
                // exclude: /\.(css|js|html)$/, //排除正則內的資源
                test: /\.(png|svg|jpg|gif)$/,
                // 這裡是匹配條件,每個選項都接收一個正則表示式或字串
                // test 和 include 具有相同的作用,都是必須匹配選項
                // exclude 是必不匹配選項(優先於 test 和 include)
                // 最佳實踐:
                // - 只在 test 和 檔名匹配 中使用正則表示式
                // - 在 include 和 exclude 中使用絕對路徑陣列
                // - 儘量避免 exclude,更傾向於使用 include
                use: ['file-loader'],
                // options: {
                //     name: "[hash:10].[ext]" //名字太長進行擷取
                // }
            }
        ]
    },
    resolve: {
        extensions: ['.js', '.json']
    },

    /*
    source-map:外聯
    inline-source-map :
    */
    devtool: "source-map", //告訴webpack提供原始碼

    plugins: [
        // 將CSS檔案從JS檔案中提取出來
        new MiniCssExtarctPlugin({
            filename: 'css/[name].[contenthash:10].css',
            path: path.resolve(__dirname, OUTPUT_FILE_NAME)
        }),
        new HtmlWebpackPlugin({
            template: "./src/index.html"
        })
    ],

    devServer: {
        port: 5000, //埠號
        contentBase: OUTPUT_FILE_NAME, //可訪問問檔案
        hot: true, //開啟HMR熱更新
        https: true, //使用https
        compress: true, // 啟用壓縮
        // proxy: {
        //     "/": "http://localhost:3000", //使用代理路徑
        // }
    },

    /** code splitting 程式碼分割
     * 當單入口時,可以將 node_modules中程式碼單獨打包成一個chunk;
     * 當多入口時,提取公共檔案單獨打包成一個chunk;
     */
    optimization: {
        splitChunks: {
            chunks: "all"
        }
    }

    /**
     * 快取:
     * Babel快取  
     *      cacheDirectory:true
     *       -->讓第二次打包更快 
     * 檔案資源快取:
     *      hash :每次webpack構建是會生成一個唯一的hash值;
     *      問題:js和css使用同一個hash值,會導致快取失效,可能值改變一個檔案;
     *      chunkhash:根據chunk生成的hash值,如果打包來自同一個chunk,那麼hash是一樣的
     *      問題:chunkhash是一樣的,因為css是在js中被引用的,屬於同一個chunk;
     *      contenthash:根據檔案內容生成hash值,不同檔案的hash值不一樣;
     *       -->讓程式碼上線執行快取更好使用 
     * 
     */

    /**
     * tree shaking:去除無用程式碼
     * 前提: 1.必須使用ES6模組化  2.開啟production環境
     * 作用: 減少程式碼體積
     * 
     * 在package.json中設定:
     *      sideEffects:false 所有程式碼都沒有副作用(都可以進行tree shaking)
     *      問題:可能會把css @babel/polyfill(副作用)檔案幹掉
     *      sideEffects:["*.css",".less"] 不會進行tree shaking
     */

    /**
     * HMR :hot module replacement 熱模組
     * 作用:一個模組發生變化指揮重新打包這個模組,並不重新打包所有。提高打包速度。
     * 樣式檔案:可以通過HMR實現,style-loader已實現
     * JS檔案:預設不使用HMR功能-->修改JS檔案程式碼,只能處理非入口檔案。
     * if(module.hot){
     *      module.hot.accept("index.js",()=>{
     *          //監聽檔案變化,一旦發生變法,其他地方不會重新打包,直接執行回撥
     *      }))
     * }
     * Html檔案:預設不使用HMR功能,同時會出問題(無需做HMR功能)
     * 解決方案:修改entry入口,引入html檔案
     * 
     * 
     */
}

wenpack.config.pro.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtarctPlugin = require("mini-css-extract-plugin"); //將css從js中提取出來
const OptiminizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //壓縮CSS
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

const OUTPUT_FILE_NAME = "dist";
module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "js/[name].[contenthash:10].js", //輸出檔名稱,hash解決快取問題,具體可見下面的解釋
        chunkFilename: 'js/[name].[contenthash:10].bundle.js', //  依賴檔名稱  
        path: path.resolve(__dirname, OUTPUT_FILE_NAME), //輸出檔案路徑
        publicPath: '/' //  公共路徑 
    },
    mode: "production", //生產環境
    module: {
        rules: [{
                test: /\.html$/,
                use: ["html-loader"]
            },
            {
                test: /\.css$/,
                use: [MiniCssExtarctPlugin.loader, "css-loader"]
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/, //處理除了nodde_modules裡的js檔案
                loader: 'babel-loader' //用babel-loader處理es6
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: ['file-loader'],
            }
        ]
    },
    devtool: "source-map", //告訴webpack提供原始碼
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            hash: true
        }),
        new MiniCssExtarctPlugin({
            filename: 'css/[name].[contenthash:10].css',
            path: path.resolve(__dirname, OUTPUT_FILE_NAME)
        }),
        /**
         * optimize-css-assets-webpack-plugin  會使webpack中自帶的JS壓縮失效,需要重新配置UglifyJsPlugin
         */
        new OptiminizeCssAssetsPlugin(),
    ],

    /** code splitting 程式碼分割
     * 當單入口時,可以將 node_modules中程式碼單獨打包成一個chunk;
     * 當多入口時,提取公共檔案單獨打包成一個chunk;
     */
    optimization: {
        splitChunks: {
            chunks: "all"
        }
    }
}