/** * webpack 通用配置 */ const path = require('path'); // path const webpack = require('webpack'); // webpack const json5 = require('json5'); // json5 const HtmlWebpackPlugin = require('html-webpack-plugin'); // webpack html 生成插件 const CopyWebpackPlugin = require('copy-webpack-plugin'); // webpack copy 插件 const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 抽取 css 插件 const { VueLoaderPlugin } = require('vue-loader'); // vue loader 插件 const ESLintPlugin = require('eslint-webpack-plugin'); // eslint 插件 const packageJson = require('./package.json'); // package.json const projectName =packageJson.name; // 项目名称 module.exports = { // 入口文件 entry: './src/main', // 输出 output: { // 输出路径(为兼容后端和多个前端项目) // 1. 兼容后端: 将 dist 目录作为资源目录, 其中 public 种的静态资源可以直接访问 // 2. 兼容多个前端项目: 每个项目发布到 public 目录下的唯一项目名称目录 path: path.resolve(__dirname, `dist/public/${projectName}`), // 输出文件名 filename: `javascript/[name].[contenthash:5].js`, // 指定发布路径,使用 auto 可具有更多灵活性 publicPath: 'auto', // 每次构建时,首先删除 output.path 目录所有内容,保证每次得到最新的构建结果 clean: true, }, module: { rules: [ // babel(包含处理: typescript) { test: /\.(t|j)s$/, exclude: /node_modules/, use: [ { loader: "babel-loader", options: { cacheDirectory: true, } } ] }, // css { test: /\.(sa|sc|c)ss$/, use: [{ loader: MiniCssExtractPlugin.loader, }, { loader: 'css-loader', }, { loader: 'postcss-loader', }] }, // 字体文件 { test: /\.(woff|woff2|eot|ttf|otf)(\?.*)?$/, type: 'asset/resource', generator: { filename: `fonts/[name].[contenthash:5].[ext]`, } }, // json5 { test: /\.json$/, type: 'json', parser: { parse: json5.parse, }, }, // vue loader { test: /\.vue$/, exclude: /node_modules/, use: [ { loader: 'vue-loader', } ] }, ], }, // 插件 plugins: [ new webpack.DefinePlugin({ __VUE_OPTIONS_API__: JSON.stringify(true), __VUE_PROD_DEVTOOLS__: JSON.stringify(false) }), // 进度显示插件 new webpack.ProgressPlugin(), // css 抽取插件 new MiniCssExtractPlugin({ filename: `css/[name].[contenthash:5].css`, chunkFilename: `css/[name].[contenthash:5].css` }), // 自动生成静态 index.html 文件 new HtmlWebpackPlugin({ template: 'public/index.html', filename: `index.html`, minify: false, inject: 'body', timestamp: new Date().getTime(), }), // 拷贝静态资源到 output.path 指定的目录 new CopyWebpackPlugin({ patterns: [ { from: 'public', toType: 'dir', filter: async (resourcePath) => { // 不复制 index.html 因为 index.html 已经由 HtmlWebpackPlugin 插件生成了 if (resourcePath.endsWith('index.html') || resourcePath.endsWith('.DS_Store')) { return false; } return true; }, info: { minimized: true }, } ] }), // vue loader 插件 new VueLoaderPlugin(), // eslint 插件 new ESLintPlugin({ fix: true, formatter: 'stylish', extensions: ['js', 'ts', 'vue', 'cjs'], exclude: [ 'node_modules', ], }), ], // 配置模块如何被解析, resolve: { // 设置模块别名,方便引用 alias: { '@': path.resolve(__dirname, 'src'), }, // 设置支持的模块扩展名,即这些扩展名的文件可以作为模块被使用 extensions: ['.ts', '.js', '.cjs', '.vue'] }, };