Webpack4.x 無分離配置

如或長夜不安發表於2018-12-27
const path = require('path');
const webpack = require('webpack');
// 刪除已經更改標籤
const CleanWebpackPlugin = require('clean-webpack-plugin');
// 分離CSS
// const ExtractTextPlugin = require("extract-text-webpack-plugin");// webpack3
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // webpack4

// 在 HTML 中新增標籤
const HtmlWebpackPlugin = require("html-webpack-plugin");

// 使用optimize-css-assets-webpack-plugin壓縮單獨的css檔案
const optimizeCss = require('optimize-css-assets-webpack-plugin');

//使用uglify-js進行js檔案的壓縮
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

// 自動補全CSS字首
const autoprefixer = require('autoprefixer');
// vue 外掛
const VueLoaderPlugin = require('vue-loader/lib/plugin')


// 這是 packet.json 中 dependencies 下的
const VENOR = [
    "lodash",
]

module.exports = {
    // bundle 和 vendor 都是自己隨便取名的,會對映到 [name] 中
    entry: {
        bundle: "./src/index.js",
        vendor: VENOR
    }, // 入口檔案
    output: {
        path: path.resolve(__dirname, '../dist'), // 必須使用絕對地址,輸出資料夾
        // 既然我們希望快取生效,就應該每次在更改程式碼以後修改檔名
        // [chunkhash]會自動根據檔案是否更改而更換雜湊
        filename: '[name].[hash].js', // 打包後輸出檔案的檔名
        publicPath: process.env.NODE_ENV === 'production' ? "./" : "/" // 知道如何尋找資源
    },
    module: {
        rules: [{
                // js檔案使用babel
                test: /\.js$/,
                use: "babel-loader",
                exclude: /node_modules/,
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: [{
                    loader: "url-loader",
                    options: {
                        name: "[name]-[hash:5].min.[ext]",
                        limit: 1000, // size <= 1KB
                        publicPath: "static/",
                        outputPath: "static/"
                    }
                }, ]
            },
            // 處理字型檔案
            {
                test: /\.(otf|eot|svg|ttf|woff|woff2)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        name: '[name].[ext]', // 打包後的檔名稱
                        outputPath: '', // 預設是dist目錄
                        publicPath: 'dist/fonts', // 圖片的url前面追加'dist/images'
                        useRelativePath: true, // 使用相對路徑
                        limit: 50000 // 表示小於1K的圖片會被轉化成base64格式
                    }
                }]
            },

            // webpack 3
            // {
            //     test: /\.css$/,
            //     loader: ExtractTextPlugin.extract({
            //         // 必須這樣寫,否則會報錯
            //         fallback: 'style-loader',
            //         use: [{
            //             loader: 'css-loader',
            //             options: {
            //                 modules: true
            //             }
            //         }]
            //     })
            // },
            // webpack4
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, // replace ExtractTextPlugin.extract({..})
                    "css-loader",
                    "postcss-loader"
                ]
            },
            // {
            //     test: /\.less$/,
            //     loader: ExtractTextPlugin.extract({
            //         // 必須這樣寫,否則會報錯
            //         fallback: 'style-loader',
            //         use: [
            //             "css-loader",
            //             "less-loader"
            //         ]
            //     })
            // }, // webpack3
            {
                test: /\.less$/,
                exclude: '/node_modules',
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: (loader) => [
                                require('postcss-import')({ root: loader.resourcePath }),
                                require('postcss-cssnext')(),
                                require('cssnano')()
                            ]
                        }
                    },
                    {
                        loader: 'less-loader', // 
                        options: {
                            importLoaders: 1
                        }
                    }
                ]
            },
        ]
    },
    resolve: { //解析模組的可選項
        modules: [
            "node_modules",
            path.resolve(__dirname, 'src')
        ],
        extensions: [".wasm", ".mjs", ".js", ".json", ".jsx"],
        alias: { //模組別名列表
            utils: path.resolve(__dirname, 'src/uils')
        }
    },
    // webpack4 用來代替webpack.optimize.CommonsChunkPlugin
    optimization: {
        runtimeChunk: {
            name: 'manifest'
        },
        minimizer: [
            // UglifyJsPlugin
            // cache 啟用檔案快取。預設的快取路徑為: node_modules/.cache/uglifyjs-webpack-plugin.
            // cacheKeys 允許重寫預設的cache keys.
            // parallel 使用多程式並行執行來提高構建速度。預設併發執行次數:os.cpus().length- 1。 
            // sourceMap 使用sourceMap將錯誤訊息位置對映到模組(這會減慢編譯速度)。如果您使用自己的minify函式,請閱讀minify部分以正確處理sourceMap。
            // minify 允許覆蓋預設的minify函式。預設外掛使用uglify-js包。
            // uglifyOptions  
            // extractComments 啟用/禁用提取註釋

            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: true,
                exclude: /node_modules/,
                uglifyOptions: {
                    warnings: false,
                    parse: {},
                    compress: {},
                    mangle: true, // Note `mangle.properties` is `false` by default.
                    output: null,
                    toplevel: false,
                    nameCache: null,
                    ie8: false,
                    keep_fnames: false,
                },
                extractComments: true,
            }),
            //壓縮CSS
            new optimizeCss({
                cssProcessor: require('cssnano'), //引入cssnano配置壓縮選項
                cssProcessorOptions: {
                    discardComments: { removeAll: true }
                },
                canPrint: true //是否將外掛資訊列印到控制檯
            }) // 普通壓縮
        ],
        splitChunks: {
            chunks: "initial", // 必須三選一: "initial" | "all"(預設就是all) | "async"
            minSize: 0, // 最小尺寸,預設0
            minChunks: 1, // 最小 chunk ,預設1
            maxAsyncRequests: 1, // 最大非同步請求數, 預設1
            maxInitialRequests: 1, // 最大初始化請求書,預設1
            name: () => {}, // 名稱,此選項課接收 function
            cacheGroups: { // 這裡開始設定快取的 chunks
                priority: "0", // 快取組優先順序 false | object |
                vendor: { // key 為entry中定義的 入口名稱
                    chunks: "initial", // 必須三選一: "initial" | "all" | "async"(預設就是非同步)
                    test: /react|lodash/, // 正則規則驗證,如果符合就提取 chunk
                    name: "vendor", // 要快取的 分隔出來的 chunk 名稱
                    minSize: 0,
                    minChunks: 1,
                    enforce: true,
                    maxAsyncRequests: 1, // 最大非同步請求數, 預設1
                    maxInitialRequests: 1, // 最大初始化請求書,預設1
                    reuseExistingChunk: true // 可設定是否重用該chunk(檢視原始碼沒有發現預設值)
                },
                css: {
                    name: 'css',
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true
                },
                less: {
                    name: 'less',
                    test: /\.less$/,
                    chunks: 'all',
                    enforce: true
                }
            }
        }
    },
    // 外掛列表
    plugins: [
        new VueLoaderPlugin(),
        // 輸出的檔案路徑
        // new ExtractTextPlugin("css/[name].[hash].css"), //  webpack 3
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename: "[name].css",
            chunkFilename: "style/[name].[id].[hash].css"
        }), // webpack 4

        // new webpack.optimize.CommonsChunkPlugin({
        //     // vendor 的意義和之前相同
        //     // manifest檔案是將每次打包都會更改的東西單獨提取出來,保證沒有更改的程式碼無需重新打包,這樣可以加快打包速度
        //     names: ['vendor', 'manifest'],
        //     // 配合 manifest 檔案使用
        //     minChunks: Infinity
        // }), // webpack4棄用 

        // 只刪除 dist 資料夾下的 bundle 和 manifest 檔案
        new CleanWebpackPlugin(['dist/bundle.*.js', 'dist/less.*.js', 'dist/css.*.js', 'dist/vendor.*.js', 'dist/styles.*.js', 'dist/style/css.*.css', 'dist/style/less.*.css', "dist/manifest.*.js"], {
            // 列印 log
            verbose: true,
            // 刪除檔案
            dry: false
        }),
        // 注意在之前 HTML 檔案中請務必刪除之前引入的 JS 檔案
        /**title : 用於生成的HTML檔案的標題。

            filename : 用於生成的HTML檔案的名稱,預設是index.html。你可以在這裡指定子目錄(例如:assets/admin.html)

            template : 模板的路徑。支援載入器,例如 html!./index.html。

            inject :true | ‘head’ | ‘body’ | false 。把所有產出檔案注入到給定的 template或templateContent。當傳入 true或者 ‘body’時所有javascript資源將被放置在body元素的底部,“head”則會放在head元素內。

            favicon : 給定的圖示路徑,可將其新增到輸出html中。

            minify : {…} | false 。傳一個html-minifier 配置object來壓縮輸出。

            hash : true | false。如果是true,會給所有包含的script和css新增一個唯一的webpack編譯hash值。這對於快取清除非常有用。

            cache : true | false 。如果傳入true(預設),只有在檔案變化時才 傳送(emit)檔案。

            showErrors : true | false 。如果傳入true(預設),錯誤資訊將寫入html頁面。

            chunks : 只允許你新增chunks 。(例如:只有單元測試塊 )

            chunksSortMode : 在chunk被插入到html之前,你可以控制它們的排序。允許的值 ‘none’ | ‘auto’ | ‘dependency’ | {function} 預設為‘auto’.

            excludeChunks : 允許你跳過一些chunks(例如,不要單元測試的 chunk).

            xhtml : 用於生成的HTML檔案的標題。

            title : true | false。如果是true,把link標籤渲染為自閉合標籤,XHTML要這麼幹的。預設false。
            */
        new HtmlWebpackPlugin({
            filename: path.resolve(__dirname, "../dist/index.html"),
            template: './index.html',
            inject: 'body',
            minify: {
                removeComments: true, //移除註釋
                collapseWhitespace: true, // 壓縮空白節點
                collapseInlineTagWhitespace: true, //壓縮行級元素的空白,會保留&nbsp;和實體空格
            }

        }),

        new webpack.ProvidePlugin({
            _: 'lodash',
        }),
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        host: 'localhost', //伺服器的ip地址
        port: 8080, //埠
        open: true, //自動開啟頁面
        hot: true, //開啟熱更新
        inline: true
    }
}

複製程式碼

對應的package.json

{
    "name": "a-vue",
    "version": "1.0.0",
    "description": "",
    "private": true,
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack  --profile --progress --colors --mode production --config config/webpack.base.js",
        "dev": "webpack-dev-server --mode development --config config/webpack.base.js"
    },
    "author": "wy",
    "license": "ISC",
    "dependencies": {
        "babel-plugin-transform-runtime": "^6.23.0",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-stage-2": "^6.24.1",
        "happypack": "^5.0.0",
        "lodash": "^4.17.2",
        "vue": "^2.5.21"
    },
    "devDependencies": {
        "autoprefixer": "^9.4.3",
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-env": "^1.6.0",
        "babel-preset-react": "^6.16.0",
        "clean-webpack-plugin": "^1.0.0",
        "css-loader": "^0.28.11",
        "cssnano": "^4.1.8",
        "extract-text-webpack-plugin": "^4.0.0-beta.0",
        "file-loader": "^1.1.11",
        "html-loader": "^0.5.5",
        "html-webpack-plugin": "^4.0.0-beta.3",
        "imagemin": "^5.3.1",
        "imagemin-pngquant": "^5.1.0",
        "img-loader": "^2.0.0",
        "less": "^3.9.0",
        "less-loader": "^4.1.0",
        "mini-css-extract-plugin": "^0.5.0",
        "optimize-css-assets-webpack-plugin": "^5.0.1",
        "postcss-cssnext": "^3.1.0",
        "postcss-import": "^12.0.1",
        "postcss-loader": "^2.1.6",
        "postcss-sprites": "^4.2.1",
        "style-loader": "^0.18.2",
        "uglifyjs-webpack-plugin": "^2.1.0",
        "url-loader": "^1.0.1",
        "vue-loader": "^15.4.2",
        "vue-style-loader": "^4.1.2",
        "vue-template-compiler": "^2.5.21",
        "webpack": "^4.16.0",
        "webpack-cli": "^3.0.8",
        "webpack-dev-server": "^3.1.14"
    }
}

複製程式碼

相關文章