配置webpack打包vue和typescript

webpack.config.js

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
const { VueLoaderPlugin } = require('vue-loader');
const { DefinePlugin } = require('webpack');
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
const workers = require('os').cpus().length;
const isDevelopment = process.env.NODE_ENV !== 'production';

module.exports = {
  entry: {
    main: "./src/main.ts",
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: "js/[contenthash:10]-[name].js",
    chunkFilename: 'js/[chunkhash:10].js',
    // assetModuleFilename:"public/media/[hash:10][ext]",
    clean: true,
  },
  mode: process.env.NODE_ENV,
  devServer: {
    port: 8080,
    hot: true,
    // open: true,
    historyApiFallback: true,
    proxy: {}
  },
  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html"
    }),
    !isDevelopment && new MiniCssExtractPlugin({
      filename: 'css/[contenthash:10]-[name].css',
      chunkFilename: '[chunkhash].css',
    }),
    new ESLintPlugin({
      exclude: "node_modules",
      context: path.resolve(__dirname, './src'),
      cache: true,
      cacheLocation: path.resolve(__dirname, "./node_modules/.cache/eslintcache")
    }),
    new VueLoaderPlugin(),
    new DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    }),
    AutoImport({
      resolvers: [ElementPlusResolver({
        importStyle: "sass"
      })],
    }),
    Components({
      resolvers: [ElementPlusResolver({
        importStyle: "sass"
      })],
    }),
    // !isDevelopment && new CopyPlugin({
    //   patterns: [
    //     { from: "./src/favicon.ico", to: "./favicon.ico" },
    //   ],
    // }),
  ].filter(Boolean),
  optimization: {
    minimize: isDevelopment ? false : true,
    minimizer: [
      new CssMinimizerPlugin(),
      // new TerserPlugin({
      //   parallel: workers, //启用多进程打包
      // })
    ],
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vue: {
          test: /[\\/]node_modules[\\/]vue(.*)?[\\/]/,
          name: "vue-chunk",
          priority: 40,
        },
        ElementPlus: {
          test: /[\\/]node_modules[\\/]element-plus(.*)?[\\/]/,
          name: "ElementPlus-chunk",
          priority: 30,
        },
        libs: {
          test: /[\\/]node_modules[\\/]/,
          name: "libs-chunk",
          priority: 20,
        }
      }
    },
  },
  resolve: {
    extensions: [".vue", ".ts", ".js"],
    extensionAlias: {
      "@": path.resolve(__dirname, "src"),
    }
  },
  devtool: isDevelopment ? "cheap-module-source-map" : "source-map",//生成map文件用于定位错误
  performance: false,
  module: {
    rules: [
      {
        test: /\.vue$/i,
        loader: "vue-loader",
        options: {// 设置缓存
          cacheDirectory: path.resolve(__dirname, '../node_modules/.cache/vue-loader')
        }
      },
      {
        test: /\.css$/i,
        use: [...CssProcess()]
      },
      {
        test: /\.less$/i,
        use: [...CssProcess("less-loader")],
      },
      {
        test: /\.s[ac]ss$/i,
        use: [...CssProcess("sass-loader")],
      },
      {
        test: /.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024//小于10kb将图片转换为base64,减少请求数量
          }
        },
        generator: {
          filename: 'public/imgs/[contenthash:10]-[name][ext]'
        }
      },
      {
        test: /\.html$/i,
        loader: "html-loader"
      },
      {
        test: /\.(eot|ttf|woff|woff2|svg|mp3|mp4|avi)$/,
        type: "asset/resource",
        generator: {
          filename: "public/media"
        }
      },
      {
        test: /\.([cm]?ts|js)$/,
        exclude: /(node_modules|bower_components)/,
        use: [
          // {
          //   loader: "thread-loader",
          //   options: {
          //     workers,
          //     workerParallelJobs: 50,
          //     workerNodeArgs: ['--max-old-space-size=1024'],
          //     poolRespawn: false,
          //     poolTimeout: 2000,
          //     poolParallelJobs: 200,
          //     name: "my-pool"
          //   },
          // },
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true, // 开启缓存
              cacheCompression: false, // 关闭压缩
            },
          },
          // {
          //   loader: "ts-loader",
          //   options: {
          //     appendTsSuffixTo: [/\.vue$/]
          //   }
          // },
        ]
      },

    ],
  }
}


function CssProcess(type) {
  return [
    isDevelopment ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: [
            ['postcss-preset-env'],
          ],
        },
      },
    },
    type
  ].filter(Boolean);

}

babel.config.js

module.exports = {
  presets: [
    "@vue/cli-plugin-babel/preset",
    [
      '@babel/preset-env',
      {
        corejs: 3,
        useBuiltIns: 'usage',
        modules: false
      }
    ],
    [
      '@babel/preset-typescript',
    ]
  ],
  plugins: [
    ["@babel/plugin-proposal-private-methods", { "loose": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    ["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
    ["@babel/plugin-transform-typescript", { "loose": true }]
  ]
}

eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    "plugin:vue/vue3-essential",
    "eslint:recommended"
  ],
  parserOptions: {
    parser: "@babel/eslint-parser"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2016",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": false
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/components/Home/.vue.ts"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  }
}

package.json

{
  "name": "src",
  "version": "1.0.0",
  "description": "",
  "main": "./src/index.ts",
  "scripts": {
    "dev": "cross-env NODE_ENV=\"development\" webpack-dev-server",
    "build": "cross-env NODE_ENV=\"production\" npx webpack --config ./webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.21.0",
    "@babel/eslint-parser": "^7.19.1",
    "@babel/plugin-proposal-private-methods": "^7.18.6",
    "@babel/plugin-syntax-typescript": "^7.20.0",
    "@babel/plugin-transform-runtime": "^7.21.0",
    "@babel/plugin-transform-typescript": "^7.21.0",
    "@babel/preset-env": "^7.20.2",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@types/react-router-dom": "^5.3.3",
    "@vue/cli-plugin-babel": "^5.0.8",
    "@vue/preload-webpack-plugin": "^2.0.0",
    "babel-loader": "^9.1.2",
    "babel-preset-react-app": "^10.0.1",
    "copy-webpack-plugin": "^11.0.0",
    "core-js": "^3.29.0",
    "cross-env": "^7.0.3",
    "css-loader": "^6.7.3",
    "css-minimizer-webpack-plugin": "^4.2.2",
    "eslint-config-react-app": "^7.0.1",
    "eslint-plugin-vue": "^9.9.0",
    "eslint-webpack-plugin": "^4.0.0",
    "html-loader": "^4.2.0",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.3",
    "less-loader": "^11.1.0",
    "mini-css-extract-plugin": "^2.7.2",
    "postcss": "^8.4.21",
    "postcss-loader": "^7.0.2",
    "postcss-preset-env": "^8.0.1",
    "react-refresh": "^0.14.0",
    "sass": "^1.58.3",
    "sass-loader": "^13.2.0",
    "style-loader": "^3.3.1",
    "thread-loader": "^3.0.4",
    "ts-loader": "^9.4.2",
    "typescript": "^4.9.5",
    "unplugin-auto-import": "^0.15.1",
    "unplugin-vue-components": "^0.24.1",
    "url-loader": "^4.1.1",
    "vue-loader": "^17.0.1",
    "vue-style-loader": "^4.1.3",
    "vue-template-compiler": "^2.7.14",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1",
    "workbox-webpack-plugin": "^6.5.4"
  },
  "browserslist": [
    "last 6 version",
    "> 1%",
    "not dead"
  ],
  "dependencies": {
    "element-plus": "^2.2.36",
    "vue": "^3.2.47",
    "vue-router": "^4.1.6"
  }
}

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值