盘他webpack5 + vue

2020-10-24  本文已影响0人  eks

细数着2020年,从疫情开始就没好事发生过,作为一个半专业的前端bug工程师看着vue3发布了,webpack5发布了,react17发布了,除了react17这一两月都在可劲的盘,今天来聊一聊盘webpack5的血泪史!

开始之前自个儿准备好node>=10,(c)npm,当然你要用yarn也可以,我这里用不了npm,用的是cnpmv6.1.1nodev12.18.4,不信你就看下面的截图:

version.png

一、首先创建文件夹webpack5,并初始化项目 cnpm init -y,得到package.json

二、安装依赖

  1. webpack相关
cnpm i -D webpack webpack-cli webpack-dev-server

安装好了webpack是如下这样的


package.png
  1. 其他依赖
cnpm i -D cross-env babel-loader html-webpack-plugin mini-css-extract-plugin clean-webpack-plugin style-loader css-loader vue-style-loader html-loader @babel/core

三、安装vue相关

cnpm i -S vue vue-router
cnpm i -D vue-template-compiler vue-loader

注意 vue和vue-template-compiler版本号一定要一样

vue.png

四、在webpack5目录下webpack.config.js

  1. 编辑config
const { resolve, join } = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成index.html
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 文本分离插件,分离js和css
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 清理垃圾文件

const { VueLoaderPlugin } = require('vue-loader'); // vue加载器
const port = 3002;
const isProd = process.env.NODE_ENV === 'production';

const cssConfig = [
    isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
    {
        loader: 'css-loader',
        options: {
            sourceMap: !isProd
        }
    }
];

const config = {
    entry: {
        index: './src/index.js' // 入口文件
    },
    output: {
        path: resolve(__dirname, 'dist'),
        filename: isProd ? 'javascript/[name].[contenthash:5].js' : '[name].js', // [name] 是entry的key
        publicPath: isProd ? './' : '/'
    },
    module: {
        rules: [
            {
                test: /\.css$/i,
                use: cssConfig
            },
            {
                test: /\.vue$/,
                use: [
                    {
                        loader: 'vue-loader',
                        options: {
                            loaders: {
                                css: cssConfig
                            },
                            preserveWhitespace: false // 不要留空白
                        }
                    }
                ],
                include: [resolve(__dirname, 'src')]
            },
            {
                test: /\.js$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: !isProd
                        }
                    }
                ],
                exclude: /node_modules/,
            },
            {
                test: /\.html$/,
                use: [{
                    loader: 'html-loader',
                    options: { // 配置html中图片编译
                        minimize: true,
                        attributes: false
                    }
                }]
            }
        ]
    },
    resolve: { // 配置路径别名
        extensions: ['.js', '.vue', '.styl'] // import引入文件的时候不用加后缀
    },
    plugins: [
        new VueLoaderPlugin(), // vue加载器
        new HtmlWebpackPlugin({
            template: join(__dirname, 'src/index.html'), // 引入模版
            filename: 'index.html',
            minify: { // 对index.html压缩
                collapseWhitespace: isProd, // 去掉index.html的空格
                removeAttributeQuotes: isProd // 去掉引号
            },
            hash: true, // 去掉上次浏览器的缓存(使浏览器每次获取到的是最新的html)
            inlineSource: '.(js|css)'
        }),
        new MiniCssExtractPlugin({ // 分离css
            filename: 'stylesheets/[name].[contenthash:5].css'
        })
    ]
};

if (isProd) {
    config.plugins.push(
        new CleanWebpackPlugin({
            verbose: true, // 打印被删除的文件
            protectWebpackAssets: false, // 允许删除cleanOnceBeforeBuildPatterns中的文件
            cleanOnceBeforeBuildPatterns: ['**/*', resolve(__dirname, 'dist')]
        }),
        new MiniCssExtractPlugin({ // 分离css
            filename: 'stylesheets/[name].[contenthash:5].css'
        })
    );
    config.optimization = { // 抽离第三方插件
        minimize: true,
        splitChunks: {
            chunks: 'all', // 必须三选一: "initial" | "all" | "async"(默认就是异步)
            minChunks: 3, // 共享最少的chunk数,使用次数超过这个值才会被提取
            maxAsyncRequests: 5, // 最多的异步chunk数
            maxInitialRequests: 5, // 最多的同步chunks数
            cacheGroups: { // 这里开始设置缓存的 chunks
                vendor: { // key 为entry中定义的 入口名称,new webpack.ProvidePlugin中的库
                    test: /node_modules/, // 正则规则验证,如果符合就提取 chunk (指定是node_modules下的第三方包)
                    // test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/, // 正则规则验证,如果符合就提取 chunk (指定是node_modules下的第三方包)
                    name: 'vendor', // 要缓存的 分隔出来的 chunk 名称
                    enforce: true,
                },
                main: {
                    test: /src/,
                    name: 'main',
                    enforce: true,
                }
            }
        },
        runtimeChunk: { name: 'runtime' } // 为每个入口提取出webpack runtime模块
    };
} else {
    config.plugins.push(
        new webpack.HotModuleReplacementPlugin(),
    );
    config.devtool = 'eval-source-map'; // 如果只用source-map开发环境出现错误定位源文件,生产环境会生成map文件
    config.devServer = {
        contentBase: join(__dirname, 'dist'), // 将 dist 目录下的文件,作为可访问文件。
        compress: true, // 开启Gzip压缩
        host: 'localhost', // 设置服务器的ip地址,默认localhost
        port, // 端口号
        open: true, // 自动打开浏览器
        hot: true,
        noInfo: true,
        overlay: { // 当出现编译器错误或警告时,就在网页上显示一层黑色的背景层和错误信息
            errors: true
        },
        disableHostCheck: true //  不检查主机
    };
}

module.exports = config;
  1. 编辑package.json
    在package.json的scripts处添加
    "dev": "cross-env NODE_ENV=development webpack-dev-server --mode development",
    "prod": "cross-env NODE_ENV=production webpack --mode production"

五、在webpack5目录下新建src目录,在src下新建index.html、index.js、router.js、App.vue、Demo.vue,编写相关代码

1.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack5</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
  1. index.js
import Vue from 'vue';
import router from './router';
import App from './App';
const isProd = process.env.NODE_ENV === 'production';
Vue.config.productionTip = isProd;

new Vue({
    router,
    render: (h) => h(App)
}).$mount('#app');

  1. router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Demo from './Demo';
Vue.use(VueRouter);
export default new VueRouter({
    routes: [
        {
            path: '/demo',
            name: 'Demo',
            component: Demo,
            meta: {
                title: 'Demo'
            }
        }
    ]
});

  1. App.vue
<template>
    <div>
    <div class="app">APP</div>
    <router-link to="/demo">to demo page</router-link>
    <router-view/>
    </div>
</template>

<script>
export default {
    name: "App"
}
</script>

<style scoped>
.app {
    font-size: 14px;
    color: aquamarine;
}
</style>

  1. Demo.vue
<template>
    <div class="demo">Demo</div>
</template>

<script>
export default {
    name: "Demo"
}
</script>

<style scoped>
.demo {
    font-size: 16px;
    color: blueviolet;
}
</style>

六、试运行
启动项目cnpm run dev

rundev.png

报错信息 Error: Cannot find module 'webpack-cli/bin/config-yargs'
大概猜测意思是找不到webpack-cli下的某个模块
在没升级到webpack5之前并没有这样的报错,这个问题使我 这半个月以来都不开心
于是我翻开以前的代码查找官方文档反复研究也没有答案,甚至翻遍全中国网都没有给我答案,欲哭无泪
于是我放弃了使用wbpack5
我想 官方的意思是,反正我是发布了,用不用随你
半个月后,wbpack5已经更新到了5.2.0,我重新入坑,既然webpack-cli@4版本没有config-yargs模块,那我用3.x版本可否?
于是我重新安装 cnpm i -D webpack-cli@3
重新启动——成功!

七、总结
由此可以看出,不是所有的新东西都是好东西,总要踩许多坑,就如我在使用webpack4的时候,升级了css-loader@4版本,编译也会报错
学习总是循序渐进的,是我太急躁不开心了半个月

上一篇下一篇

猜你喜欢

热点阅读