Webpack常用配置及打包vue

222 阅读1分钟
  1. 安装webpack``webpack-cli
npm install webpack webpack-cli -D
  1. 配置入口出口
// webpack.config.js
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  }
}
  1. 处理sass
    1. 安装sass``sass-loader``postcss-loader``css-loader``style-loader
npm install sass sass-loader postcss-loader css-loader style-loader -D
    1. 添加postcss.config.js
module.exports = {
  plugins: [
    require('postcss-preset-env')
  ]
}
    1. 添加rules
module: {
  rules: [
    {
      test: /.(s[ac]ss|css)$/,
      use: [
        { loader: 'style-loader' },
        { loader: 'css-loader' },
        { loader: 'postcss-loader' },
        { loader: 'sass-loader' }
      ]
    },
  ]
}
  1. 处理图片等文件资源和字体
  • v5已经可以试用asset替代file-loader url-loader``raw-loader
  • 添加rules
  module: {
    rules: [
      {
        test: /.(png|svg|jpg|jpeg|git)$/i,
        type: "asset",
        generator: {
          filename: "img/[name].[hash:6][ext]"
        },
        parser: {
          dataUrlCondition: {
            maxSize: 100 * 1024
          }
        }
      },
      {
        test: /.(woff2?|eot|ttf)$/,
        type: "asset/resource",
        generator: {
          filename: "font/[name].[hash:6][ext]"
        }
      }
    ]
  },

  1. 自动清理dist目录
npm install clean-webpack-plugin -D

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

  plugins: [
    new CleanWebpackPlugin()
  ]
  1. 打包html
npm install html-webpack-plugin -D

const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
  new HtmlWebpackPlugin({
        title: 'webpack案例',
        template: './index.html'
  }),
]
  1. 自定义模板需要数据填充,需要defineplugin 已内置
new DefinePlugin({
      BASE_URL: '"./"'
}),

  1. 自动复制public的内容到dist
npm install copy-webpack-plugin -D

    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'public',
          globOptions: {
            ignore: [
              '**/.DS_Store',
              '**/index.html'
            ]
          }
        }
      ]
    })
  1. 支持ES6 安装babel
    1. 安装babel
npm install babel-loader @babel/core -D
    1. 安装预设
npm install @babel/preset-env
    1. 新增rules
{
  test: /.m?js$/,
  use: {
    loader: "babel-loader",
    options: {
      presets: [
        ["@babel/preset-env"]
      ]
    }
  }
}
    1. 也可以在babel.config.js配置预设
module.exports = {
  presets: [
    ["@babel/preset-env"]
  ]
}

\

\

打包vue

\

  1. 添加@vue/compiler-sfc vue-loader
ni @vue/compiler-sfc vue-loader -D

const { VueLoaderPlugin } = require('vue-loader/dist/index')


{
  test: /.vue$/,
  loader: "vue-loader"
}

new VueLoaderPlugin()
  1. public/index.html
<!DOCTYPE html>
<html lang="en">
  <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>hello</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
  1. src/app.vue
<template>
  <div>
    <h1>aoo</h1>
    <p>hello</p>
  </div>
</template>

<script>
export default {}
</script>

<style lang="scss" scoped></style>
  1. src/index.js
import { createApp } from 'vue/dist/vue.esm-bundler'
import App from './App.vue'
import './style.scss'

// vue代码
createApp(App).mount('#app')

\

搭建本地服务器

webpack-dev-server

  • 安装
npm install webpack-dev-server -D
  • 配置webpack.config.js
devServer: {
    static: {
      directory: path.join(__dirname, './')
    },
    compress: true,
    hot: true,
    //host: '0.0.0.0',  // 表示在同一个网段下所有主机
    port: 8000,
    open: true,
    proxy: {
      "/api": {
        target: "http://localhost:8888",
        pathRewrite: {
          "^/api": ""
        },
        secure: false,
        changeOrigin: true   //修改源
      }
    }
  },
  • 配置package.json
"scripts": {
    "build": "webpack --watch",
    "serve": "webpack serve"
  },
  • 使用nr serve启动\

  • 开启HMR

    • 修改webpack配置

配置devServer

 devServer: {
    static: {
      directory: path.join(__dirname, './')
    },
    compress: true,
    hot: true,
    //host: '0.0.0.0',  // 表示在同一个网段下所有主机
    port: 8000,
    open: true,
    proxy: {
      "/api": {
        target: "http://localhost:8888",
        pathRewrite: {
          "^/api": ""
        },
        secure: false,
        changeOrigin: true   //修改源
      }
    }
  },

resolve模块解析

  • extensions解析到文件时自动添加扩展名 即可以省略后缀引入
  • alias取别名
resolve: {
    extensions: ['.js', '.json'],
    alias: path.resolve(__dirname, './src/js')
  }

\

分离不同环境的配置

  • webpack.comm.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
const { VueLoaderPlugin } = require('vue-loader/dist/index');

module.exports = {
  target: "web",
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../build"),
    filename: "js/bundle.js",
  },
  resolve: {
    extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"],
    alias: {
      "@": path.resolve(__dirname, "../src"),
      "js": path.resolve(__dirname, "../src/js")
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      // },
      {
        test: /.(jpe?g|png|gif|svg)$/,
        type: "asset",
        generator: {
          filename: "img/[name]_[hash:6][ext]",
        },
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024,
          },
        },
      },
      {
        test: /.(eot|ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "font/[name]_[hash:6][ext]",
        },
      },
      {
        test: /.js$/,
        loader: "babel-loader"
      },
      {
        test: /.vue$/,
        loader: "vue-loader"
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      title: "哈哈哈哈"
    }),
    new DefinePlugin({
      BASE_URL: "'./'",
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    }),
    new VueLoaderPlugin()
  ],
};
  • webpack.dev.config.js
const { merge } = require('webpack-merge');

const commonConfig = require('./webpack.comm.config');

module.exports = merge(commonConfig, {
  mode: "development",
  devtool: "source-map",
  devServer: {
    contentBase: "./public",
    hot: true,
    // host: "0.0.0.0",
    port: 7777,
    open: true,
    // compress: true,
    proxy: {
      "/api": {
        target: "http://localhost:8888",
        pathRewrite: {
          "^/api": ""
        },
        secure: false,
        changeOrigin: true
      }
    }
  },
})
  • webpack.prod.config.js
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const {merge} = require('webpack-merge');

const commonConfig = require('./webpack.comm.config');

module.exports = merge(commonConfig, {
  mode: "production",
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: "./public",
          globOptions: {
            ignore: [
              "**/index.html"
            ]
          }
        }
      ]
    }),
  ]
})
  • package.json
"scripts": {
    "build": "webpack --config ./config/webpack.prod.config.js",
    "serve": "webpack serve --config ./config/webpack.dev.config.js"
  },

\

完整webpack配置

  • webpack.config.js
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');

module.exports = {
  target: "web",
  mode: "development",
  devtool: "source-map",
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "./build"),
    filename: "js/bundle.js",
  },
  devServer: {
    contentBase: "./public",
    hot: true,
    // host: "0.0.0.0",
    port: 7777,
    open: true,
    // compress: true,
    proxy: {
      "/api": {
        target: "http://localhost:8888",
        pathRewrite: {
          "^/api": ""
        },
        secure: false,
        changeOrigin: true
      }
    }
  },
  resolve: {
    extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"],
    alias: {
      "@": path.resolve(__dirname, "./src"),
      "js": path.resolve(__dirname, "./src/js")
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      // },
      {
        test: /.(jpe?g|png|gif|svg)$/,
        type: "asset",
        generator: {
          filename: "img/[name]_[hash:6][ext]",
        },
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024,
          },
        },
      },
      {
        test: /.(eot|ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "font/[name]_[hash:6][ext]",
        },
      },
      {
        test: /.js$/,
        loader: "babel-loader"
      },
      {
        test: /.vue$/,
        loader: "vue-loader"
      }
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      title: "哈哈哈哈"
    }),
    new DefinePlugin({
      BASE_URL: "'./'",
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    }),
    // new CopyWebpackPlugin({
    //   patterns: [
    //     {
    //       from: "public",
    //       to: "./",
    //       globOptions: {
    //         ignore: [
    //           "**/index.html"
    //         ]
    //       }
    //     }
    //   ]
    // }),
    new VueLoaderPlugin()
  ],
};