使用Webpack5搭建项目(vue篇)

本篇承接使用Webpack搭建项目(react篇)

由于大部分配置一样,我们从上一篇react项目中,复制webpack.dev.js以及webpack.prod.js

开发模式

1.删除ReactRefreshWebpackPlugin

2.自动补充拓展名修改为.vue文件,同时处理js文件,不是jsx

const path = require("path")
const EslintWebpackPlugin = require("eslint-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
//返回处理样式的loader函数
let getStyleLoaders=function(pre){
    return[
        "style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre
    ].filter(Boolean)
}
module.exports = {
    entry: "./src/main.js",
    output: {
        path: undefined,
        filename: "static/js/[name].js",
        chunkFilename: "static/js/[name].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]"
    },
    module: {
        rules: [
            // 处理css
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader'),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader'),
            },
            //处理图片
            {
                test:/\.(jpe?g|png|gif|webp|svg)$/,
                type:"asset",
                parser:{
                    dataCondition:{
                        maxSize:10*1024, //小于10kb以下可以转为base64,减少请求数量
                    }
                }
            },
            // 处理其他资源
            {
                test:/\.(woff2?|ttf)$/,
                type:"asset/resource",
            },
            //处理js
            {
                test:/\.js$/,
                include:path.resolve(__dirname,'../src'),
                loader:"babel-loader",
                options:{
                    cacheDirectory:true,
                    cacheCompression:false,
                }
            }
        ]
    },
    plugins:[
        new EslintWebpackPlugin({
            context:path.resolve(__dirname,'../src'),
            exclude:'node_modules',
            cache:true,
            cacheLocation:path.resolve(__dirname,'../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"../public/index.html"),
        }),
    ],
    mode:"development",
    devtool:"cheap-module-source-map",
    optimization:{
        splitChunks:{
            chunks:"all" //代码分割
        },
        runtimeChunk:{
            name:entrypoint=>`runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        }
    },
    //webpack解析块加载选项
    resolve:{
        //自动补全文件拓展名
        extensions:[".vue",".js",".json"]
    },
    devServer:{
        host:"localhost",
        port:3000,
        open:true,
        hot:true,
        historyApiFallback:true//解决前端路由刷新404的问题
    }
}

3.配置vue loader

npm init -y

npm install -D vue-loader vue-template-compiler
const { VueLoaderPlugin } = require('vue-loader')



let getStyleLoaders = function (pre) {
    return [
        "vue-style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre
    ].filter(Boolean)
}


{
                test: /\.vue$/,
                loader: 'vue-loader'
            }


plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        new VueLoaderPlugin()
    ],

接下来下载依赖:

npm i eslint-webpack-plugin html-webpack-plugin vue-style-loader css-loader postcss-loader postcss-preset-env -D

npm i less-loader sass-loader stylus-loader sass babel-loader vue-loader webpack webpack-cli webpack-dev-server -D

新建配置.eslintrc.js

npm i @babel/eslint-parser -D
module.exports={
    root:true, //根目录就是当前
    env:{
        node:true //启用node中的变量
    },
    extends:["plugin:vue/vue3-essential","eslint:recommended"],//无需安装,已经内置有
    parserOptions:{
        parser:"@babel/eslint-parser" //需要安装
    }
}

新建配置babel.config.js

npm i @vue/cli-plugin-babel -D
module.exports={
    presets:["@vue/cli-plugin-babel/preset"]
}

补全src文件以及public文件,下载vue(默认vue3)

npm i vue
//main.js
import {createApp} from "vue"
import App from "./App"

createApp(App).mount(document.getElementById("app"))
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue-cli</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>
//App.vue
<template>
    <h1 class="title">hello app!</h1>
</template>
<script>
export default{
    name:"App"
}
</script>
<style lang="less">
.title{
    color:red
}
</style>

配置package.json

 npm i cross-env -D
"scripts": {
    "start":"npm run dev",
    "dev":"cross-env NODE_ENV=development webpack serve --config ./config/webpack.dev.js"
  },
npm i eslint-plugin-vue -D

然后输入 npm start ,发现如下警告:

5cabc19c8f774f40b8270ed4a89b39e5.png

我们需要定义这两个标识:

const {DefinePlugin} = require("webpack")




plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],

在编译就解决了,热模块更新HMR,都已内置,无需再配置了。

下面配置一下路由:

npm i vue-router

router.js

import { createRouter, createWebHistory } from "vue-router";

export default createRouter({
    history:createWebHistory(),
    routes:[
        {
            path:"/home",
            component:()=>import ("../views/Home/Home.vue")
        },
        {
            path:"/about",
            component:()=>import ("../views/About/About.vue")
        }
    ]
})

main.js

import {createApp} from "vue"
import App from "./App"
import router from "./router/router"

createApp(App).use(router).mount(document.getElementById("app"))

以上就是开发环境的基本配置,webpack.dev.js代码如下:

const path = require("path")
const EslintWebpackPlugin = require("eslint-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const { VueLoaderPlugin } = require('vue-loader')
const {DefinePlugin} = require("webpack")
//返回处理样式的loader函数
let getStyleLoaders = function (pre) {
    return [
        "vue-style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre
    ].filter(Boolean)
}
module.exports = {
    entry: "./src/main.js",
    output: {
        path: undefined,
        filename: "static/js/[name].js",
        chunkFilename: "static/js/[name].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]"
    },
    module: {
        rules: [
            // 处理css
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader'),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader'),
            },
            //处理图片
            {
                test: /\.(jpe?g|png|gif|webp|svg)$/,
                type: "asset",
                parser: {
                    dataCondition: {
                        maxSize: 10 * 1024, //小于10kb以下可以转为base64,减少请求数量
                    }
                }
            },
            // 处理其他资源
            {
                test: /\.(woff2?|ttf)$/,
                type: "asset/resource",
            },
            //处理js
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                loader: "babel-loader",
                options: {
                    cacheDirectory: true,
                    cacheCompression: false,
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],
    mode: "development",
    devtool: "cheap-module-source-map",
    optimization: {
        splitChunks: {
            chunks: "all" //代码分割
        },
        runtimeChunk: {
            name: entrypoint => `runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        }
    },
    //webpack解析块加载选项
    resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"]
    },
    devServer: {
        host: "localhost",
        port: 3000,
        open: true,
        hot: true,
        historyApiFallback: true//解决前端路由刷新404的问题,主要解决history模式i,hash模式没有该问题。
    }
}

 生产模式

修改和优化webpack.prod.js,修改只处理js文件,添加vue-loader,修改devtool,修改文件补充的拓展

{
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                loader: "babel-loader",
                options: {
                    cacheDirectory: true,
                    cacheCompression: false,
                }
            },
const { VueLoaderPlugin } = require('vue-loader')
const {DefinePlugin} = require("webpack")



plugins: [
        ...
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],
devtool: "source-map",
resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"]
    }

添加favicon.ico图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    <title>vue-cli</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

下载依赖:

npm i mini-css-extract-plugin css-minimizer-webpack-plugin copy-webpack-plugin -D

npm install image-minimizer-webpack-plugin imagemin --save-dev

//无损

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev

开发模式基本配置完毕,webpack.prod.js代码如下:

const path = require("path")
const EslintWebpackPlugin = require("eslint-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin = require("terser-webpack-plugin")
const ImageMinimizerWebpackPlugin = require("image-minimizer-webpack-plugin")
const CopyWebpackPlugin = require("copy-webpack-plugin")
const { VueLoaderPlugin } = require('vue-loader')
const {DefinePlugin} = require("webpack")
//返回处理样式的loader函数
let getStyleLoaders = function (pre) {
    return [
        MiniCssExtractPlugin.loader, "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre
    ].filter(Boolean)
}
module.exports = {
    entry: "./src/main.js",
    output: {
        path: path.resolve(__dirname, "../dist"),
        filename: "static/js/[name].[contenthash:10].js",
        chunkFilename: "static/js/[name].[contenthash:10].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]",
        clean: true
    },
    module: {
        rules: [
            // 处理css
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader'),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader'),
            },
            //处理图片
            {
                test: /\.(jpe?g|png|gif|webp|svg)$/,
                type: "asset",
                parser: {
                    dataCondition: {
                        maxSize: 10 * 1024, //小于10kb以下可以转为base64,减少请求数量
                    }
                }
            },
            // 处理其他资源
            {
                test: /\.(woff2?|ttf)$/,
                type: "asset/resource",
            },
            //处理js
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                loader: "babel-loader",
                options: {
                    cacheDirectory: true,
                    cacheCompression: false,
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
        }),
        new CopyWebpackPlugin({//复制到dist文件下
            patterns: [
                {
                    from: path.resolve(__dirname, "../public"), to: "../dist", globOptions: {
                        ignore: ["**/index.html", "**/ignored-directory/**"],//忽略Index.html文件
                    },
                }
            ]
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],
    mode: "production",
    devtool: "source-map",
    optimization: {
        splitChunks: {
            chunks: "all" //代码分割
        },
        runtimeChunk: {
            name: entrypoint => `runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        },
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin(),
            new ImageMinimizerWebpackPlugin({
                minimizer: {
                    implementation: ImageMinimizerWebpackPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ]
    },
    //webpack解析块加载选项
    resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"]
    }
}

合并开发和生产模式 

复制webpack.prod.js为webpack.config.js


const isProduction = process.env.NODE_ENV == "production"


output: {
        path: isProduction?path.resolve(__dirname, "../dist"):undefined,
        filename:isProduction? "static/js/[name].[contenthash:10].js":"static/js/[name].js",
        chunkFilename: isProduction? "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].[contenthash:10].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]",
        clean: true
    },



plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        isProduction && new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyWebpackPlugin({//复制到dist文件下
            patterns: [
                {
                    from: path.resolve(__dirname, "../public"), to: "../dist", globOptions: {
                        ignore: ["**/index.html", "**/ignored-directory/**"],//忽略Index.html文件
                    },
                }
            ]
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ].filter(Boolean),
devtool: isProduction? "source-map":"cheap-module-source-map",
optimization: {
        splitChunks: {
            chunks: "all" //代码分割
        },
        runtimeChunk: {
            name: entrypoint => `runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        },
        minimize:isProduction,
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin(),
            new ImageMinimizerWebpackPlugin({
                minimizer: {
                    implementation: ImageMinimizerWebpackPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ]
    },
devServer: {
        host: "localhost",
        port: 3000,
        open: true,
        hot: true,
        historyApiFallback: true//解决前端路由刷新404的问题
    }

修改package.json指令:

"scripts": {
    "start": "npm run dev",
    "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
  },

然后输入指令尝试打包和编译,合并就是这些,webpack.config.js完整代码如下:

const path = require("path")
const EslintWebpackPlugin = require("eslint-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin = require("terser-webpack-plugin")
const ImageMinimizerWebpackPlugin = require("image-minimizer-webpack-plugin")
const CopyWebpackPlugin = require("copy-webpack-plugin")
const { VueLoaderPlugin } = require('vue-loader')
const {DefinePlugin} = require("webpack")

const isProduction = process.env.NODE_ENV == "production"

console.log(isProduction);
//返回处理样式的loader函数
let getStyleLoaders = function (pre) {
    return [
        isProduction?MiniCssExtractPlugin.loader:"vue-style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre
    ].filter(Boolean)
}
module.exports = {
    entry: "./src/main.js",
    output: {
        path: isProduction?path.resolve(__dirname, "../dist"):undefined,
        filename:isProduction? "static/js/[name].[contenthash:10].js":"static/js/[name].js",
        chunkFilename: isProduction? "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].[contenthash:10].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]",
        clean: true
    },
    module: {
        rules: [
            // 处理css
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader'),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader'),
            },
            //处理图片
            {
                test: /\.(jpe?g|png|gif|webp|svg)$/,
                type: "asset",
                parser: {
                    dataCondition: {
                        maxSize: 10 * 1024, //小于10kb以下可以转为base64,减少请求数量
                    }
                }
            },
            // 处理其他资源
            {
                test: /\.(woff2?|ttf)$/,
                type: "asset/resource",
            },
            //处理js
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                loader: "babel-loader",
                options: {
                    cacheDirectory: true,
                    cacheCompression: false,
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        isProduction && new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyWebpackPlugin({//复制到dist文件下
            patterns: [
                {
                    from: path.resolve(__dirname, "../public"), to: "../dist", globOptions: {
                        ignore: ["**/index.html", "**/ignored-directory/**"],//忽略Index.html文件
                    },
                }
            ]
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ].filter(Boolean),
    mode:isProduction? "production":"development",
    devtool: isProduction? "source-map":"cheap-module-source-map",
    optimization: {
        splitChunks: {
            chunks: "all" //代码分割
        },
        runtimeChunk: {
            name: entrypoint => `runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        },
        minimize:isProduction,
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin(),
            new ImageMinimizerWebpackPlugin({
                minimizer: {
                    implementation: ImageMinimizerWebpackPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ]
    },
    //webpack解析块加载选项
    resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"]
    },
    devServer: {
        host: "localhost",
        port: 3000,
        open: true,
        hot: true,
        historyApiFallback: true//解决前端路由刷新404的问题
    }
}

拓展:配置element-plus

 npm i element-plus

我们配置按需引入:

npm install -D unplugin-vue-components unplugin-auto-import

修改webpack.config.js文件

const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        isProduction && new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyWebpackPlugin({//复制到dist文件下
            patterns: [
                {
                    from: path.resolve(__dirname, "../public"), to: "../dist", globOptions: {
                        ignore: ["**/index.html", "**/ignored-directory/**"],//忽略Index.html文件
                    },
                }
            ]
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__: true,
            __VUE_PROD_DEVTOOLS__: false
        }),
        AutoImport({
            resolvers: [ElementPlusResolver()],
        }),
        Components({
            resolvers: [ElementPlusResolver()],
        }),
    ].filter(Boolean),

引入即可:

<template>
    <h1 class="title">hello app!</h1>
    <ElButton>按钮</ELButton>
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>
    <!-- <Home />
    <About /> -->
    <router-view></router-view>
</template>
<script>
import Home from "./views/Home/Home"
import About from "./views/About/About"
import {ElButton} from 'element-plus'
export default{
    name:"App",
    components:{Home,About,ElButton}
}
</script>
<style lang="less">
.title{
    color:red
}
</style>

修改主题:

创建index.scss文件在src下:

@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  ),
);

 配置webpack.config.js

let getStyleLoaders = function (pre) {
    return [
        isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre &&{
            loader:pre,
            options:pre=="sass-loader"?{
                additionalData: `@use "@/styles/elementPlus/index.scss" as *;`,
            }:{}
        }
    ].filter(Boolean)
}

配置别名:

resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"],
        alias:{
            "@":path.resolve(__dirname,"../src")
        }
    },
Components({
            resolvers: [ElementPlusResolver({
                //自定义主题配置引入sass
                importStyle: "sass"
            })],
        }),

配置后即可查看页面,配置成功。Button 按钮 | Element Plus

优化一下cacheGroup的配置:我们希望打包可以分开打包:

optimization: {
        splitChunks: {
            chunks: "all", //代码分割
            cacheGroups:{
                vue:{ // 一起打包成一个js文件
                    test:/[\\/]node_modules[\\/]vue(.*)?[\\/]/,
                    name:'chunk-vue',
                    priority:40, //打包优先级权重
                },
                elementPlus:{ //antd单独打包
                    test:/[\\/]node_modules[\\/]element-plus[\\/]/,
                    name:'chunk-elementPlus',
                    priority:30,
                },
                lib:{ //node_modules单独打包
                    test:/[\\/]node_modules[\\/]/,
                    name:'chunk-lib',
                    priority:20,
                },
            }
        },

关闭性能分析:

performance:false,

webpack内部做一下缓存:

{
                test: /\.vue$/,
                loader: 'vue-loader',
                options:{
                    //开启缓存提高第二次打包速度
                    cacheDirectory:path.resolve(__dirname,"../node_modules/.cache/vue-loader")
                }
            }

 开启webpack内部缓存,有助于下次的打包编译节省时间:

cache: { //可开启webpack5内置缓存
        type: 'filesystem',
        allowCollectingMemory: true
    }

我们就完成了配置:

const path = require("path")
const EslintWebpackPlugin = require("eslint-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin = require("terser-webpack-plugin")
const ImageMinimizerWebpackPlugin = require("image-minimizer-webpack-plugin")
const CopyWebpackPlugin = require("copy-webpack-plugin")
const { VueLoaderPlugin } = require('vue-loader')
const { DefinePlugin } = require("webpack")
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

const isProduction = process.env.NODE_ENV == "production"

//返回处理样式的loader函数
let getStyleLoaders = function (pre) {
    return [
        isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader", "css-loader", {
            //处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: ["postcss-preset-env"]
                }
            }
        },
        pre &&{
            loader:pre,
            options:pre=="sass-loader"?{
                additionalData: `@use "@/styles/elementPlus/index.scss" as *;`,
            }:{}
        }
    ].filter(Boolean)
}
module.exports = {
    entry: "./src/main.js",
    output: {
        path: isProduction ? path.resolve(__dirname, "../dist") : undefined,
        filename: isProduction ? "static/js/[name].[contenthash:10].js" : "static/js/[name].js",
        chunkFilename: isProduction ? "static/js/[name].[contenthash:10].chunk.js" : "static/js/[name].[contenthash:10].chunk.js",
        assetModuleFilename: "static/media/[hash:10][ext][query]",
        clean: true
    },
    module: {
        rules: [
            // 处理css
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader'),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader'),
            },
            //处理图片
            {
                test: /\.(jpe?g|png|gif|webp|svg)$/,
                type: "asset",
                parser: {
                    dataCondition: {
                        maxSize: 10 * 1024, //小于10kb以下可以转为base64,减少请求数量
                    }
                }
            },
            // 处理其他资源
            {
                test: /\.(woff2?|ttf)$/,
                type: "asset/resource",
            },
            //处理js
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                loader: "babel-loader",
                options: {
                    cacheDirectory: true,
                    cacheCompression: false,
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
            }
        ]
    },
    plugins: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache')
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        isProduction && new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyWebpackPlugin({//复制到dist文件下
            patterns: [
                {
                    from: path.resolve(__dirname, "../public"), to: "../dist", globOptions: {
                        ignore: ["**/index.html", "**/ignored-directory/**"],//忽略Index.html文件
                    },
                }
            ]
        }),
        new VueLoaderPlugin(),
        //cross-env定义的环境变量给webpack使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告问题
        new DefinePlugin({
            __VUE_OPTIONS_API__: true,
            __VUE_PROD_DEVTOOLS__: false
        }),
        //按需加载element-plus
        AutoImport({
            resolvers: [ElementPlusResolver()],
        }),
        Components({
            resolvers: [ElementPlusResolver({
                //自定义主题配置引入sass
                importStyle: "sass"
            })],
        }),
    ].filter(Boolean),
    mode: isProduction ? "production" : "development",
    devtool: isProduction ? "source-map" : "cheap-module-source-map",
    optimization: {
        splitChunks: {
            chunks: "all", //代码分割
            cacheGroups:{
                vue:{ // 一起打包成一个js文件
                    test:/[\\/]node_modules[\\/]vue(.*)?[\\/]/,
                    name:'chunk-vue',
                    priority:40, //打包优先级权重
                },
                elementPlus:{ //antd单独打包
                    test:/[\\/]node_modules[\\/]element-plus[\\/]/,
                    name:'chunk-elementPlus',
                    priority:30,
                },
                lib:{ //node_modules单独打包
                    test:/[\\/]node_modules[\\/]/,
                    name:'chunk-lib',
                    priority:20,
                },
            }
        },
        runtimeChunk: {
            name: entrypoint => `runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化
        },
        minimize: isProduction,
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin(),
            new ImageMinimizerWebpackPlugin({
                minimizer: {
                    implementation: ImageMinimizerWebpackPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ]
    },
    //webpack解析块加载选项
    resolve: {
        //自动补全文件拓展名
        extensions: [".vue", ".js", ".json"],
        alias:{
            "@":path.resolve(__dirname,"../src")
        }
    },
    devServer: {
        host: "localhost",
        port: 3000,
        open: true,
        hot: true,
        historyApiFallback: true//解决前端路由刷新404的问题
    },
    performance:false,
    cache: { //可开启webpack5内置缓存
        type: 'filesystem',
        allowCollectingMemory: true
    }
}

猜你喜欢

转载自blog.csdn.net/m0_59962790/article/details/130416199