Webpack5 Vue3 手动搭建脚手架

548 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

记录第一次手动搭建脚手架,之后会用这个脚手架完成一个vue项目。
所以这个文章后面可能随着项目的需求而增加设置。

一 配置webpack

下载webpack

npm init -y
// 初始化项目

npm i -D webpack webpack-cli

配置webpack.config.js

1.在根目录下创建src文件夹,添加main.js

// webpack.config.js
const path = require('path');
const { resolve } = path;

const config = {
  mode: 'development',
  //开发模式
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    // [name]保持和entry文件名一致
    // [contenthash] md4-hash of the output file content版本后缀
    clean:true
    // 每次build删除上一版本
  },
}

module.exports = config;

2.在package.json中添加script,这时候可以运行第一次npm run dev,打包成功后进入接下来的配置。

//package.json
  "scripts": {
    "dev": "webpack"
  }
  1. 添加html-webpack-plugin插件
    这个插件是为了在dist文件夹下自动生成html文件, 具体文档
npm i -D html-webpack-plugin
// webpack.config.js

const path = require('path');
const { resolve } = path;
const HtmlWebpackPlugin = require('html-webpack-plugin');

const config = {
  mode: 'development',
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    clean:true
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './index.html'),
      // 目标文件,在根目录下创建index.html
      filename: 'index.html', 
      title: 'Webpack App'
      // index.html的title
    })
  ]
};

module.exports = config;
  1. 根目录下创建index.html文件
//index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
  1. 在main.js添加任意代码,再次运行npn run dev。
    成功后,打开dist文件夹下的index.html,用live-server打开查看。
// main.js
const root = document.getElementById('root');
root.textcontent = 'hello world';

image.png

二 配置vue3

下载vue

npm i vue@next -S

在src目录下创建App.vue

image.png

接下来就是熟悉的内容

//main.js
import { createApp } from "vue";
import App from './App.vue';

const app = createApp(App);

app.mount('#root');

vue loader

npm i -D vue-loader@next
//webpack.config.js
const path = require('path');
const { resolve } = path;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');
const webpack = require('webpack');

const config = {
  mode: 'development',
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    clean:true
  },
  module: {
    rules: [
        {
            test: /\.vue$/,
            use: [
                'vue-loader'
            ]
        },
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './index.html'),
      filename: 'index.html', 
      title: 'Webpack App'
    }),
    new VueLoaderPlugin(),
    // Define Bundler Build Feature Flags
    new webpack.DefinePlugin({
        // Drop Options API from bundle
        // 这两个不配置的话,在打包后会出warning
        // webpack官方文档没搜到,最后是在stackoverflow里找到的问答
        // https://stackoverflow.com/questions/64081026/how-use-bundler-build-feature-flags-in-vue-3-0-with-webpack
        __VUE_OPTIONS_API__: false,
        __VUE_PROD_DEVTOOLS__: false
    }),
  ]
};

module.exports = config;

style-loader css loader

下载

npm i -D css-loader style-loader

如果使用stylus scss 等预处理器,还需要下载vue-style-loader
相关doc

//webpack.config.js
const path = require('path');
const { resolve } = path;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');
const webpack = require('webpack');

const config = {
  mode: 'development',
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    clean:true
  },
  module: {
    rules: [
        {
            test: /\.vue$/,
            use: [
                'vue-loader'
            ]
        },
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader'
            ]
        }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './index.html'),
      filename: 'index.html', 
      title: 'Webpack App'
    }),
    new VueLoaderPlugin(),
    // Define Bundler Build Feature Flags
    new webpack.DefinePlugin({
        // Drop Options API from bundle
        __VUE_OPTIONS_API__: false,
        __VUE_PROD_DEVTOOLS__: false
    }),
  ]
};

module.exports = config;

可以给App,vue中的style添加样式,再次运行npm run dev查看dist/index.html。
每次添加完新东西就重新打包很重要,因为很可能某一步就会出错。

image.png

三 配置babel

babel loader

下载

npm i -D @babel/core @babel/preset-env babel-loader

配置babel.config.js

babel.config.json
这里我尝试用babel.config.json 配置targets
但是写了官方给的 "targets": "> 0.25%, not dead"之后,总是会显示unknow option .presets
没有找到原因,但是.json文件里的"targets"后面似乎只能用{}。

.browserslist
我还尝试了用.browserslist配置,是可以的。 最后,选择了.js的方法配置。

webpack的官方文档里,还有一种是在babel-loader里直接配置。 但是显示的案例使用的是webpack4.x,所以我没有尝试。 webpack.js.org/loaders/bab…

module.exports = {
  presets: [
    ["@babel/preset-env", {
      "targets": "> 0.25%, not dead"
    }]
  ]
}

添加corejs

参考文章 官方文档

npm install --save-dev @babel/plugin-transform-runtime
// 关于下面这两个为什么下载为dependency而不是devdependency,官方的解释
// The transformation plugin is typically used only in development, but the runtime itself will be depended on by your deployed code.
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs3

配置webpack.config.js

const path = require('path');
const { resolve } = path;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');
const webpack = require('webpack');

const config = {
  mode: 'development',
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    clean:true
  },
  module: {
    rules: [
        {
            test: /\.vue$/,
            use: [
                'vue-loader'
            ]
        },
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader'
            ]
        },
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './index.html'),
      filename: 'index.html', 
      title: 'Webpack App'
    }),
    new VueLoaderPlugin(),
    // Define Bundler Build Feature Flags
    new webpack.DefinePlugin({
        // Drop Options API from bundle
        __VUE_OPTIONS_API__: false,
        __VUE_PROD_DEVTOOLS__: false
    }),
  ]
};

module.exports = config;

接下来,可以在App.vue的script部分写一些代码,npm run dev 查看打包的情况。

四 配置 devServer

下载

npm install --save-dev webpack-dev-server

配置webpack.config.js

const path = require('path');
const { resolve } = path;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');
const webpack = require('webpack');

const config = {
  mode: 'development',
  entry: {
    main: './src/main.js'
  },
  output: {
    path: resolve(__dirname, 'dist'), 
    filename: '[name][contenthash].js',
    clean:true
  },
  // 顺便配置了debug工具
  devtool: 'source-map',
  devServer: {
    static: {
        // 文件地址
        directory: resolve(__dirname, 'dist')
    },
    // 端口
    port: 3000,
    // 自动打开浏览器
    open: true,
    hot: true,
    compress: true,
    // 遇到404返回主页
    historyApiFallback:true
  },
  module: {
    rules: [
        {
            test: /\.vue$/,
            use: [
                'vue-loader'
            ]
        },
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader'
            ]
        },
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './index.html'),
      filename: 'index.html', 
      title: 'Webpack App'
    }),
    new VueLoaderPlugin(),
    // Define Bundler Build Feature Flags
    new webpack.DefinePlugin({
        // Drop Options API from bundle
        __VUE_OPTIONS_API__: false,
        __VUE_PROD_DEVTOOLS__: false
    }),
  ]
};

module.exports = config;

五 配置Eslint

下载

npm install --save-dev eslint
// plugin:vue/vue3-essential
npm install --save-dev eslint-plugin-vue
npm install --save-dev @babel/eslint-parser
npm install --save-dev eslint-webpack-plugin

webpack eslint plugin
How to use ESLint in Webpack 5
eslint-plugin-vue

配置 webpack.config.js

//webpack.config.js
...
  plugins: [
    ...
    new ESLintPlugin({
      extensions: ['js', 'json', 'vue'],
      exclude: 'node_modules',
      // 只有error会中断编译,warning不会
      quiet: true
    })
  ]
...

配置 .eslintrc.js

module.exports = {
    root: true,
    env: {
      node: true
    },
    'extends': [
      'plugin:vue/vue3-essential',
      //这里也可以不是recommended,我是按照vue cli的选项照搬的
      'eslint:recommended'
    ],
    parserOptions: {
      // vue cli这里是没有@babel前缀的
      parser: '@babel/eslint-parser'
    },
    rules: {
      'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
      'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
      'no-unused-vars': 'warn'
    },
    // eslint不会扫描dist文件夹内的js文件
    ignorePatterns: ['dist']
}

参考文章:
Vue 3 和 Webpack 5 来了,手动搭建的知识该更新了 - 掘金 (juejin.cn)
webpack-suppress-eslint-warnings-on-browser-console
webpack-eslint-configuration new-eslintoptions