使用webpack5搭建vue3脚手架

1、项目初始化

npm init -y // 创建package.json

仿照官方脚手架创建好项目的目录结构,router和views文件夹可以不用加

使用webpack5搭建vue3脚手架_第1张图片

2、项目的打包配置

const { Configuration } = require('webpack')
const path = require('path')
const os = require('os')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index')
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
//进度条插件
const WebpackBar = require('webpackbar')
const CopyPlugin = require('copy-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// 代码压缩
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 压缩图片
const ImageMinimizerWebpackPlugin = require('image-minimizer-webpack-plugin')

// 需要通过 cross-env 定义环境变量
const isProduction = process.env.NODE_ENV === "production"

// cpu核心数量
const threads = os.cpus().length

const getStyleLoaders = (preProcessor) => {
  return [
    isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader',
    'css-loader',
    // css 兼容处理
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: ['postcss-preset-env']
        }
      }
    },
    // 如果传入其它loader就使用这个loader
    preProcessor && {
      loader: preProcessor
    }
  ].filter(Boolean)
}

/**
 * @type {Configuration} // 配置智能提示
 */
module.exports = {
  entry: './src/main.ts',
  output: {
    path: isProduction ? path.resolve(__dirname, 'dist') : undefined,
    filename: isProduction ? 'js/[name].[contenthash:10].js' : 'js/[name].js',
    // 异步加载的文件
    chunkFilename: isProduction ? 'js/[name].[contenthash:10].chunk.js' : 'js/[name].chunk.js',
    // 静态文件
    assetModuleFilename: 'asset/[hash:10][ext][query]',
    clean: true,
    pathinfo: false,
    publicPath: '/'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader', // 内部会给vue文件注入HMR功能代码
        options: {
          // 开启缓存
          cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/vue-loader'),
        }
      },
      {
        test: /\.css$/,
        use: getStyleLoaders()
      },
      {
        test: /\.less$/,
        use: getStyleLoaders('less-loader')
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true, // 开启babel编译缓存
          cacheCompression: false, // 缓存文件不要压缩

        }
      },
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: ['ts-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders('sass-loader')
      },
      {
        test: /.(png|jpe?g|gif|svg)$/,
        type: 'asset/imgs',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 图片大于10*1024进行base54转码
          }
        },
        generator: {
          filename: 'asset/imgs/[hash][ext][query]' // 局部指定输出位置
        }
      },
      {
        test: /\.(ttf|woff2?|mp4|mp3|avi)$/,
        type: 'asset/resource',
        generator: {
          filename: 'asset/media/[hash][ext][query]'
        }
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'asset/fonts/[hash][ext][query]'  // 局部指定输出位置
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    new VueLoaderPlugin(),
    new webpack.DefinePlugin({
      __VUE_OPTIONS_API__: true, // 开启optionAPI
      __VUE_PROD_DEVTOOLS__: false,
      'process.env': {
        VUE_APP_HOST: isProduction  // 将属性转化为全局变量,让代码中可以正常访问
      }
    }),
    new CleanWebpackPlugin(), // 清除上次打包的产物
    new WebpackBar(),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'public'),
          to: path.resolve(__dirname, 'dist'),
          toType: 'dir',
          noErrorOnMissing: true,
          globOptions: {
            ignore: ['**/index.html'],
          },
          info: {
            minimized: true,
          }
        }
      ]
    }),
    // 提取css成单独文件
    isProduction &&
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: 'asset/css/[name].[hash:10].css',
      chunkFilename: 'asset/css/[name].[contenthash:10].css'
    }),

  ].filter(Boolean),
  // 代码处理
  optimization: {
    // 告知webpack使用TerserPlugin 或其它在 optimization.minimizer定义的插件压缩 bundle
    minimize: isProduction,
    // 压缩的操作
    minimizer: [
      new CssMinimizerPlugin(),  // 压缩css
      // 当前生产模式下会默认开启TerserPlugin,压缩javascript,但是我们需要其它配置,就需要重写了
      new TerserWebpackPlugin({
        parallel: threads, // 开启多进程处理,填入数字是开启几个线程
        terserOptions: {
          compress: {
            drop_console: true, // 删除所有的console.log语句
          }
        }
      }),
      // 压缩图片
      new ImageMinimizerWebpackPlugin({
        minimizer: {
          implementation: ImageMinimizerWebpackPlugin.imageminGenerate,
          options: {
            plugins: [
              ['gifsicle', { interlaced: true }],
              ['jpegtran', { progressive: true }],
              ['optipng', { optimizationLevel: 5 }],
              [
                'svg0',
                {
                  plugins: [
                    'preset-default',
                    'prefixIds',
                    {
                      name: 'sortAttrs',
                      params: {
                        xmlnsOrder: 'alphabetical'
                      }
                    }
                  ]
                }
              ]
            ]
          }
        }
      })
    ],
    // 拆包区域
    splitChunks: {
      chunks: 'all',  // 指定打包加载是同步加载还是异步加载
      // name: '[id].[hash:10]',  // 如果名字有冲突可以设置一个单独的名字
      // name: '[name].[chunkhash:10]',
      cacheGroups: {
        // elementplus
        // elementplus: {
        //   name: 'chunk-elementplus',
        //   test: /[\\/]node_modules[\\/]_?element-pluse(.*)/,
        //   priority: 30,
        // },
        // 将vue 相关的代码库单独打包,减少node_modules的chunk体积
        vue: {
          name: 'vue',
          test: /[\\/]node_modules[\\/]vue(.*)/,
          chunks: 'initial',
          priority: 20,
        },
        libs: {
          name: 'chunk-libs',
          test: /[\\/]node_modules[\\/]/,
          priority: 10, // 权重最低,优先考虑前面的内容
          chunks: 'initial',
        }
      }
    },
    // 为运行时代码创建一个额外的 chunk,减少 entry chunk 体积,提高性能
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`
    }
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    },
    // 需要解析的文件类型列表。由于 webpack 的解析顺序是从左到右,因此要将使用频率高的文件类型放在左侧,如下我将 vue 放在最左侧。
    extensions: ['.vue', '.ts', '.js', '.tsx', '.json'],
    // 指定查找依赖包目录
    modules: ['node_modules'],
    fallback: { "stream": false },  // vue-loader 相关报错解决办法
  },
  mode: isProduction ? 'production' : 'development',
  devServer: {
    port: 3000,
    open: true,
    hot: true, // 热模块更新
    compress: true,
    historyApiFallback: true, // 解决 vue-loader 刷新404问题
  },
  // 错误代码信息标注,第一个是行,第二个是行加列,关闭默认按照最大性能处理,开启方便查错
  devtool: isProduction ? 'source-map' : 'cheap-source-map',
  performance: false
}

package.json添加运行和打包命令

    "dev": "webpack-dev-server",
    "build": "webpack"

为了方便npm install 附上package.json文件

{
  "name": "vue-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@vue/cli-plugin-babel": "^5.0.8",
    "babel-loader": "^9.1.3",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^11.0.0",
    "css-loader": "^6.8.1",
    "css-minimizer-webpack-plugin": "^5.0.1",
    "html-webpack-plugin": "^5.5.3",
    "image-minimizer-webpack-plugin": "^3.8.3",
    "mini-css-extract-plugin": "^2.7.6",
    "postcss-loader": "^7.3.3",
    "postcss-preset-env": "^9.3.0",
    "sass": "^1.69.5",
    "sass-loader": "^13.3.2",
    "scss": "^0.2.4",
    "scss-loader": "^0.0.1",
    "style-loader": "^3.3.3",
    "terser-webpack-plugin": "^5.3.9",
    "ts-loader": "^9.5.0",
    "vue-loader": "^17.3.1",
    "vue-style-loader": "^4.1.3",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1",
    "webpackbar": "^5.0.2"
  },
  "dependencies": {
    "vue": "^3.3.8",
    "vue-router": "^4.2.5"
  }
}

在main.ts中引入vue并且创建app挂载到app上

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.use(router)
app.mount('#app')

需要添加描述文件,否则无法识别 .vue 文件

declare module '*.vue'{
  import { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

3、运行和打包

执行 npm run dev运行项目,项目成功启动
使用webpack5搭建vue3脚手架_第2张图片

使用webpack5搭建vue3脚手架_第3张图片

使用 npm run build 查看打包效果,成功
使用webpack5搭建vue3脚手架_第4张图片
附上源码地址:https://github.com/h1456796723/vue3-cli

你可能感兴趣的:(javascript,前端,vue.js)