webpack学习笔记-使用webpack构建vue

77 阅读3分钟
  • package.json 文件 以下依赖包我是跟着视频一一学习下载的,并不是在项目中所需要,不一定全部下载。
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "./src/main.js",
  "scripts": {
    "start": "npm run dev",
    "dev": "webpack serve --config ./config/webpack.dev.js",
    "build": "webpack --config ./config/webpack.prod.js"
  },
  "repository": {
    "type": "git",
    "url": "git@gitee.com:king-cui/webpack_code.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.21.0",
    "@babel/core": "^7.21.0",
    "@babel/plugin-transform-runtime": "^7.21.0",
    "@babel/preset-env": "^7.20.2",
    "@vue/cli-plugin-babel": "^5.0.8",
    "babel-loader": "^9.1.2",
    "core-js": "^3.29.1",
    "css-loader": "^6.7.3",
    "css-minimizer-webpack-plugin": "^4.2.2",
    "eslint": "^8.36.0",
    "eslint-plugin-import": "^2.27.5",
    "eslint-plugin-vue": "^9.10.0",
    "eslint-webpack-plugin": "^4.0.0",
    "html-webpack-plugin": "^5.5.0",
    "image-minimizer-webpack-plugin": "^3.8.2",
    "imagemin": "^8.0.1",
    "imagemin-gifsicle": "^7.0.0",
    "imagemin-jpegtran": "^7.0.0",
    "imagemin-optipng": "^8.0.0",
    "imagemin-svgo": "^10.0.1",
    "less": "^4.1.3",
    "less-loader": "^11.1.0",
    "mini-css-extract-plugin": "^2.7.5",
    "sass": "^1.58.3",
    "sass-loader": "^13.2.0",
    "style-loader": "^3.3.1",
    "stylus": "^0.59.0",
    "stylus-loader": "^7.1.0",
    "thread-loader": "^3.0.4",
    "vue-loader": "^17.0.1",
    "vue-style-loader": "^4.1.3",
    "vue-template-compiler": "^2.7.14",
    "webpack": "^5.76.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1",
    "workbox-webpack-plugin": "^6.5.4"
  },
  "dependencies": {
    "@vue/preload-webpack-plugin": "^2.0.0",
    "vue": "^3.2.47"
  }
}

  • webpack.dev.js 文件 这个文件是我们进行开发环境的配置。
const os = require("os")
const path = require("path") // node.js核心模块。我们这里来处理路径问题
const Eslint = require('eslint-webpack-plugin')
const { DefinePlugin } = require("webpack")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const threads = os.cpus().length
module.exports = {
  // 入口  
  entry: './src/main.js', // 这里是相对路径
  // 输出
  output: {
    path: undefined ,  // 开发模式不需要输出
    filename: 'js/[name].js', //打包打包生成的文件名称
    chunkFilename: "js/chunk-[name].js", // 打包输出的其他文件命名
    assetModuleFilename: 'media/[hash:10][ext][query]',
  },
  devtool:"cheap-module-source-map",
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "8083", // 端口号
    open: true, // 是否自动打开浏览器
    hot: true // 是否开启HMR(默认值为true)
  },
  // 加载器
  module: {
    rules: [
        // 每个文件只能被一个loader处理,不在遍历所有loader
          // loader
          {
            test: /\.css$/i,
            use: ["vue-style-loader", "css-loader"],
          
          },
          // less-loader
          {
            test: /\.less$/i,
            use: ["vue-style-loader", "css-loader", "less-loader"], // 执行顺序从左到右
          
          },
          // sass-loader
          {
            test: /\.s[ac]ss$/i,
            use: ["vue-style-loader", "css-loader", "sass-loader"], // 执行顺序从左到右
          
          },
          {
            test: /\.styl$/,
            // loader 只能引入一个loader use 可以引入多个文
            use: ["vue-style-loader", "css-loader", "stylus-loader"], // 执行顺序从左到右
          },
          {
            test: /\.(png|jpg|gif)$/i,
            type: "asset",  //资源模块
            // generator: {
            //   //[hash:10] 打包出来的图片名称为hash值,长度10位
            //   filename:'image/[hash:10][ext][query]'
            // },
            parser: {
              dataUrlCondition: {
                maxSize: 10 * 1024 // 10kb
              }
            }
          },
          {
            test: /\.(ttf|woff2?)$/i,
            type: "asset/resource",  //资源模块
            // generator: {
            //   //[hash:10] 打包出来的图片名称为hash值,长度10位
            //   filename:'media/[hash:10][ext][query]'
            // },
          },
          {
            test: /\.m?js$/,
            //  exclude: /node_modules/, // 排除node-module的文件转换
            include: path.resolve(__dirname,'../src'), // 只处理src下面的文件,其他文件不解析
            use: [
              {
                loader: 'thread-loader', // 开启多进程
                options: {
                  // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者
                  workers: threads // 
                },
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true, // 开启babel缓存
                  cacheCompression: false, //关闭babel缓存的zip压缩
                  plugins: ['@babel/plugin-transform-runtime'] // 减少babel编译后的代码体积
                },
              },
            ]
          },
          {
            test: /\.vue$/,
            loader: "vue-loader"
          }
    ]
  },
  // 插件
  plugins: [
    new Eslint({
      // 哪些文件我们检查,这里我们检测src下面的文件
      context: path.resolve(__dirname, "../src"),
      exclude: 'node_modules', // exclude的默认值也是“node_modules”
      cache: true, // 开启缓存
      cacheLocation: path.resolve(__dirname, "../node_modules/.cache/eslintcache"), // 缓存文件的位置。
      threads: true, // 开启多进程
    }),
    new HtmlWebpackPlugin({
      // 以public/index.html为模板创建一个html,切自动引入打包好的依赖
      template: path.resolve(__dirname, "../public/index.html")
    }),
    new VueLoaderPlugin(),
    // cross-env 定义的环境变量给打包工具使用的
    // DefinePlugin定义的环境变量是给源代码使用的,
    new DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    })
  ],
  optimization: {
    splitChunks: {
      // 但入口文件仅需配置chunks为all
      chunks: "all"
    },
    // 可以对输出资源文件进行更好的命名,将来好做缓存。
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`,
    },
  },
  //文件扩展名
  resolve: {
    // 自动补全文件扩展名
    extensions:[".vue", ".js", ".json"]
  },
  // 模式
  mode: 'development'
}
  • webpack.prod.js 文件 这个文件就是我们生产打包的配置。
const os = require("os")
const path = require("path") // node.js核心模块。我们这里来处理路径问题
const Eslint = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); //css 压缩
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 提取css成单独文件
const TerserPlugin = require("terser-webpack-plugin")   // 用来压缩js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); // 压缩图片
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin")
const { DefinePlugin } = require("webpack")
const { VueLoaderPlugin } = require('vue-loader')
const WorkboxPlugin = require('workbox-webpack-plugin'); // 离线
const threads = os.cpus().length
module.exports = {
  // 入口  
  entry: './src/main.js', // 这里是相对路径
  // 输出
  output: {
    path:path.resolve(__dirname, "../dist") ,  // 这里是绝对路径 'dist',打包生成的文件夹名称
    filename: 'js/[name].[contenthash:10].js', //打包打包生成的文件名称
    chunkFilename: "js/chunk-[name].[contenthash:10].js", // 打包输出的其他文件命名
    assetModuleFilename: 'media/[hash:10][ext][query]',
    clean: true, // 在生成文件之前清空 output 目录
  },
  // 映射
  devtool:"source-map",
  // 加载器
  module: {
    rules: [
      {
        oneOf: [
           // loader
          {
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader"],
          
          },
          // less-loader
          {
            test: /\.less$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"], // 执行顺序从左到右
          
          },
          // sass-loader
          {
            test: /\.s[ac]ss$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"], // 执行顺序从左到右
          
          },
          {
            test: /\.styl$/,
            // loader 只能引入一个loader use 可以引入多个文
            use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"], // 执行顺序从左到右
          },
          {
            test: /\.(png|jpg|gif)$/i,
            type: "asset",  //资源模块
            parser: {
              // 如果一个模块的资源大小小于 maxSize, 那么模块会被作为一个Base64编码的字符串注入到包中,否则模块文件会被生成到输出目标中。  
              dataUrlCondition: {
                maxSize: 10 * 1024 // 10kb
              }
            }
          },
          {
            test: /\.(ttf|woff2?)$/i,
            type: "asset/resource",  //资源模块
          },
          {
            test: /\.m?js$/,
            //exclude: /node_modules/, // 排除node-module的文件转换
            include: path.resolve(__dirname,'../src'), // 只处理src下面的文件,其他文件不解析
            use: [
              {
                loader: 'thread-loader', // 开启多进程
                options: {
                  // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者
                  workers: threads // 
                },
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true, // 开启babel缓存
                  cacheCompression: false, //关闭babel缓存的zip压缩
                  plugins: ['@babel/plugin-transform-runtime'] // 减少babel编译后的代码体积
                },
              },
            ]
          },
        
        ]
      },
      {
        test: /\.vue$/,
        loader: "vue-loader"
      }
    ]
  },
  // 插件
  plugins: [
    new Eslint({
      // 哪些文件我们检查,这里我们检测src下面的文件
      context: path.resolve(__dirname, "../src"),
      exclude: 'node_modules', // 排除node-module的文件转换
      cache: true, // 开启缓存
      cacheLocation: path.resolve(__dirname, "../node_modules/.cache/eslintcache"), // 缓存文件的位置。
      threads: true, // 开启多进程
    }),
    new HtmlWebpackPlugin({
      // 以public/index.html为模板创建一个html,切自动引入打包好的依赖
      template: path.resolve(__dirname, "../public/index.html")
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:10].css',
      chunkFilename: "css/chunk-[name].[contenthash:10].css", // css打包输出的其他文件命名
    }),
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何“旧的” ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    }),
    new PreloadWebpackPlugin({
      // rel: "preload",
      // as:"script"
      rel: "prefetch"
    }),
    new VueLoaderPlugin(),
        // cross-env 定义的环境变量给打包工具使用的
    // DefinePlugin定义的环境变量是给源代码使用的,
    new DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    })
  ],
  optimization: {
    minimizer: [
      // 压缩css
      new CssMinimizerPlugin(),
      // 压缩js
      new TerserPlugin({
        parallel: threads  // 开启多线程
      }),
      // 压缩图片
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminGenerate,
          options: {
            plugins: [
              ['gifsicle', { interlaced: true }],
              ['jpegtran', { progressive: true }],
              ['optipng', { optimizationLevel: 5 }],
              ['svgo', {
                plugins: [
                  'preset-default',
                  'prefixIds',
                  {
                    name:"sortAttrs",
                    params: {
                      xmlnsorder:"alphabetical",
                    }
                  }
                ]
              }]
            ]
          }
        }
      }),
    ],
    splitChunks: {
      // 但入口文件仅需配置chunks为all
      chunks: "all"
    },
    // 可以对输出资源文件进行更好的命名,将来好做缓存。
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`,
    },
  },
  resolve: {
    // 自动补全文件扩展名
    extensions:[".vue", ".js", ".json"]
  },
  // 模式
  mode: 'production'
}

  • Babel.config.js文件 项目的辅助配置,和项目的package.json同级。
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: "usage", // 对core.js按需加载
        corejs: 3
      }
    ],
    "@vue/cli-plugin-babel/preset"
  ]
};

  • .eslintrc.js 文件 项目的辅助配置,和项目的package.json同级。
module.exports = {
  extends: ["plugin:vue/vue3-essential","eslint:recommended"],
  env: {
    node: true,  //启用node中全局变量
    browser: true, // 启用浏览器中全局变量
  },
  parserOptions: {
    ecmaVersion: 6,  // es版本为6
    sourceType: "module", //es模块 module
  },
  rules: {
    "no-var": 2
  },
  plugins: ['import'],
}