Webpack5从零搭建Vue2项目


从零搭建Vue2项目

Owner: fredbrock

目的

复习下Webpack基础知识。

初始Webpack项目

mkdir vue2-webpack-template
cd vue2-webpack-template
pnpm init
pnpm add -D webpack webpack-cli webpack-dev-server

创建项目目录结构

├── .gitignore
├── build
│  ├── webpack.dev.config.js
│  └── webpack.prod.config.js
├── package.json
├── pnpm-lock.yaml
├── public
│  ├── favicon.ico
│  ├── img
│  ├── index.html
│  └── robots.txt
├── README.md
└── src
  ├── App.vue
  ├── assets
  │  └── logo.png
  ├── components
  │  └── HelloWorld.vue
  ├── HomeView.vue
  └── main.js

webpack.dev.config.js:本地开发服务 webpack.prod.config.js:打包生产环境 public: 静态资源文件夹 src:Vue源码目录

创建源代码

安装 Vue 项目依赖

pnpm add -S vue@2

创建入口文件: src/main.js

import Vue from "vue";
import App from "./App.vue";

Vue.config.productionTip = false;

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

创建 Vue 根实例: src/App.vue

<template>
  <div id="app">Hello Vue~</div>
</template>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

创建 index.html 模板 public/index.html


<!DOCTYPE html>
<html lang="">
  <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><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

配置 Vue SFC 支持

安装 Vue SFC 依赖

pnpm add -D html-webpack-plugin
pnpm add -D vue-loader@15 vue-template-compiler css-loader vue-style-loader
pnpm add -D less less-loader

创建webpack基本配置:build/webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");

module.exports = {
  mode: "development",
  entry: path.resolve(__dirname, "../src/main.js"),
  output: {
    filename: "[name].[hash].js",
    path: path.resolve(__dirname, "../dist"),
  },
  module: {
    rules: [
      // ... other rules
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
      {
        test: /\.css$/,
        use: ["vue-style-loader", "css-loader"],
      },
      {
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          "vue-style-loader",
          "css-loader",
          "less-loader",
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "Vue.js",
      template: path.resolve(__dirname, "../public/index.html"),
      filename: "index.html",
      inject: true,
    }),
    new VueLoaderPlugin(),
  ],
};

将css打包到单独的文件

{
  test: /\.less$/i,
  use: [
    MiniCssExtractPlugin.loader,
    // "vue-style-loader",
    "css-loader",
    "less-loader",
  ],
},
{
  test: /\.css$/,
  use: [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            [
              "postcss-preset-env",
              {
                // Options
              },
            ],
          ],
        },
      },
    },
    "less-loader",
  ],
},

配置 Babel

安装 Babel 依赖

pnpm add -D @babel/core @babel/preset-env babel-loader 

配置 Babel

{
  test: /\.(?:js|mjs|cjs)$/,
  exclude: /node_modules/,
  use: {
    loader: "babel-loader",
    options: {
      presets: [["@babel/preset-env", { targets: "defaults" }]],
    },
  },
},

配置 clean-webpack-plugin

 pnpm add -D clean-webpack-plugin
  plugins: [
    new CleanWebpackPlugin(),
  ],

配置打包命令: package.json


  "scripts": {
    "build": "webpack --config build/webpack.config.js"
  },

配置汇总

完整包依赖安装命令

mkdir vue2-webpack-template
cd vue2-webpack-template
pnpm init
pnpm add -D webpack webpack-cli webpack-dev-server
pnpm add -D html-webpack-plugin
pnpm add -S vue@2
pnpm add -D vue-loader@15 vue-template-compiler css-loader vue-style-loader
pnpm add -D less less-loader
pnpm add -D mini-css-extract-plugin
pnpm add -D @babel/core @babel/preset-env babel-loader 
pnpm add -D clean-webpack-plugin

完整 webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); 

module.exports = {
  mode: "development",
  entry: path.resolve(__dirname, "../src/main.js"), //入口文件
  output: {
    filename: "[name].[hash].js",
    path: path.resolve(__dirname, "../dist"),
  },
  devServer: {
    static: {
      directory: path.join(__dirname, "public"),
    },
    compress: true,
    hot: true,
    port: 9000,
  },
  module: {
    rules: [
      {
        test: /\.(?:js|mjs|cjs)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [["@babel/preset-env", { targets: "defaults" }]],
          },
        },
      },
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
      {
        test: /\.less$/i,
        use: [
          MiniCssExtractPlugin.loader,
          // "vue-style-loader",
          "css-loader",
          "less-loader",
        ],
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env",
                    {
                      // Options
                    },
                  ],
                ],
              },
            },
          },
          "less-loader",
        ],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new webpack.DefinePlugin({
      BASE_URL: "./",
    }),
    new HtmlWebpackPlugin({
      title: "Custom template using Handlebars",
      template: path.resolve(__dirname, "../public/index.html"),
      filename: "index.html",
      inject: true,
    }),
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: "style.css",
    }),
  ],
};

package.json

{
  "name": "vue-webpack-cli",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "serve": "webpack serve --config build/webpack.dev.config.js",
    "build": "webpack --config build/webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "vue": "^2.7.16"
  },
  "devDependencies": {
    "@babel/core": "^7.25.2",
    "@babel/preset-env": "^7.25.3",
    "babel-loader": "^9.1.3",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^7.1.2",
    "html-webpack-plugin": "^5.6.0",
    "less": "^4.2.0",
    "less-loader": "^12.2.0",
    "mini-css-extract-plugin": "^2.9.0",
    "postcss": "^8.4.41",
    "postcss-loader": "^8.1.1",
    "postcss-preset-env": "^10.0.0",
    "style-loader": "^4.0.0",
    "vue-loader": "^15.11.1",
    "vue-style-loader": "^4.1.3",
    "vue-template-compiler": "^2.7.16",
    "webpack": "^5.93.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.0.4"
  }
}

完整代码

https://github.com/FredBrock/vue2-webpack-template

效果图

参考