阅读 174
webpack5+vue搭建vue脚手架

webpack5+vue搭建vue脚手架

搭建背景:webpack5正式版已经发布有一段时间了,但vue-cli还是有webpack4,这样导致webpack5的新功能不能发挥,特别是摇树,缓存等功能

项目目录结构

src
├── assets(静态资源)
├── style(样式文件)
├── utils(公共函数目录)
├── views(vue页面目录)
├── App.vue
├── index.html(模板文件)
├── index.js(入口文件)
复制代码

搭建步骤

  1. 搭建基础配置

    1. 添加入口,出口配置
    const { resolve } = require("path")
    module.exports = {
        entry: resolve(__dirname, 'src/index.js'),
        output: {
            filename: '[name][contenthash:8].js',
            path: resolve(__dirname, 'dist'),
            clean: true,
        },
    }
    复制代码
    1. 添加html模板解析
    const { resolve } = require("path")
    module.exports = {
        plugins:[
          new HtmlWebpackPlugin({
             template: resolve(__dirname, 'src/index.html'),
             //<title><%=htmlWebpackPlugin.options.title %></title>
             //注意htmlWebpackPlugin首写字母小写
             title: "webpack5-vue"
         }),
        ]
    }
    复制代码
    1. 添加资源解析
    module.exports = {
     module: {
         rules: [
             /**webpack5合成了资源模块,会自动处理图片,字体等等资源文件,
              * 因此不需要使用loader
              */
             {
                 test: /\.(jpe?g|png|gif|svg)$/i,
                 type: 'asset',
                 parser: {
                     dataUrlCondition: {
                         maxSize: 4 * 1024 // 4kb
                     }
                 },
                 generator: {
                     //单独修改生成路径
                     filename: 'img/[hash:8][ext][query]'
                 }
             },
             {
                 test: /\.(ttf|woff2)$/i,
                 type: 'asset',
                 generator: {
                     //单独修改生成路径
                     filename: 'font/[hash:8][ext][query]'
                 }
             },
         ]
     },
    }
    复制代码
    1. 添加引用解析
    const { resolve } = require("path")
    module.exports = {
        resolve: {
         alias: {
             '@': resolve(__dirname, 'src'),
         }
     }
    }
    复制代码
    1. 添加vue-loader
    const { VueLoaderPlugin } = require('vue-loader')
    module.exports = {
    module: {
         rules: [
             {
                 test: /\.vue$/i,
                 loader: 'vue-loader'
             },
           ]
        }
        plugins:[
          new VueLoaderPlugin(),
        ]
    }
    复制代码
  2. 搭建开发环境

const { resolve } = require("path")
const { merge } = require("webpack-merge")
const base = require("./webpack.base")
const cssLoader = ['vue-style-loader', 'css-loader']
//通过webpack-merge合并基础配置
module.exports =  merge(base,{
    mode: "development",
    module: {
        rules: [
            {
                test: /\.css$/i,
                use: cssLoader,
            },
            {
                test: /\.scss$/i,
                use: [...cssLoader, 'sass-loader']
            },
            {
                test: /\.(js|vue)$/i,//添加eslint检查
                enforce: 'pre',//强制优先允许,防止与babel发生冲突
                exclude: /node_modules/,
                loader: 'eslint-loader',//eslint-loader配置请查看后方.eslintrc.js文件
                options: {
                    fix: true//自定修复语法错误
                }
            },
        ]
    },
    devtool: 'eval-cheap-module-source-map',
    devServer: {
        compress: true,
        static: {
            directory: resolve(__dirname, 'dist'),
        },
        liveReload: true,//启用热更新
    },
    target: "web",//启用热更新需配置target:"web"
    cache: true,
    resolve: {
        alias: {
            //解析import Vue from 'vue'时,查找vue的路径
            vue$: resolve(__dirname, 'node_modules/vue/dist/vue.esm.js'),
        }
    },
})
复制代码
  1. 搭建发布环境
const { resolve } = require("path")
const { merge } = require("webpack-merge")
const base = require("./webpack.base")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

const cssLoader = [MiniCssExtractPlugin.loader, 'css-loader', {
    loader: 'postcss-loader',//css自动兼容
    options: {
        postcssOptions: {
            plugins: [
                [
                    'postcss-preset-env',
                    {
                        // 其他选项
                    },
                ],
            ]
        }
    }
}]
module.exports = merge(base, {
    mode: "production",
    output: {
        environment: {
            //不要使用箭头模式,兼容IE9
            arrowFunction: false
        },
        //统一修改资源生成路径
        assetModuleFilename: 'assets/[hash:8][ext][query]',
    },
    module: {
        rules: [
            {
                test: /\.js$/i,
                exclude: /node_modules/,
                use: [{
                    loader: 'babel-loader',
                    /**
                     * package.json配置
                     * "browserslist": [
                            "> 1%",
                            "last 2 versions",
                            "not ie <= 8"
                        ]
                     */
                    //可以将配置单独抽离到.babelrc文件
                    options: {
                        cacheDirectory: true,
                        presets: [
                            [
                                "@babel/preset-env",
                                {
                                    modules: false,
                                    useBuiltIns: "usage",
                                    corejs: 3
                                }
                            ]
                        ]
                    }
                }],
            },
            {
                test: /\.css$/i,
                use: cssLoader,
            },
            {
                test: /\.scss$/i,
                use: [...cssLoader, 'sass-loader']
            },
        ]
    },
    // devtool:'none',
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'style/[name][contenthash:8].css'
        }),
    ],
    resolve: {
        alias: {
            vue$: resolve(__dirname, 'node_modules/vue/dist/vue.min.js')
        }
    },
    optimization: {
        //sideEffects:true要配合package.json的sideEffect字段使用,
        //package.json的sideEffect配置如下:true 所有代码都有副作用(不要删除),false(都可以删除),数组(那些文件不要删除)
        //sideEffects开启后,样式被去掉解决方法:
        //1. 其实我们可以使用require的方式,动态的引入css样式,从而避免被tree shaking摇掉。require('./style.css')
        //2. 对css文件不做tree shaking,在package.json的sideEffect中加入数组,[ “*.css” ],不对css文件进行tree shaking。[推荐]
        sideEffects: true,//tree shaking Commonjs也支持了
        // minimize:true,
        minimizer: [
            `...`,//保留默认配置,否则js不压缩
            new CssMinimizerPlugin(),//压缩css
        ],
        splitChunks: {//chunk切割,提取公共代码,减小主包大小
            // include all types of chunks
            chunks: 'all',
            cacheGroups: {
                vue: {
                    name: 'chunk-vue',
                    test: /[\\/]node_modules[\\/](vue|vuex|vue-router)[\\/]/,
                    chunks: 'all',
                    priority: -10
                },
                elementUi: {
                    name: 'chunk-element-ui',
                    test: /[\\/]node_modules[\\/]element-ui[\\/]/,
                    chunks: 'all',
                    priority: -9
                }
            }

        },
    },
})
复制代码
  1. .eslintrc.js配置

    1.通过命令npx eslint --init 生成.eslintrc.js配置,选择支持vuejs,运行环境选择node,自动生成配置文件

module.exports = {
    "env": {
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:vue/essential",
    ],
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "vue"
    ],
};
复制代码

2.添加 eslint-config-airbnb-bas规则

"extends": [
        "eslint:recommended",
        "plugin:vue/essential",
        "airbnb-base"
    ],
复制代码

3.添加自有规则

    "rules": {
        "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
        'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
        'import/no-unresolved': [
            'off',
            {
                ignore: ['^@/'], // @ 是设置的路径别名
            },
        ],
        "semi": ["error", "never"],//分号
        "quotes": ["error", "single"],//字符串“”
    }
复制代码
文章分类
前端
文章标签