花了差不多一天多的时间, 重新撸了一遍 webpack4.x 的常用配置.
github 详细代码地址, 如有帮助, 请赐我一颗小星星. https://github.com/pomelott/webpack4.x_Demo
基本上常用的配置都熟悉了一遍, 总体上来讲, 为了对 parcel 进行反击, webpack 从 4.x 开始, 正在朝着尽可能的简化配置文件的方向发展.
一, 首先来看下, webpack4 的新特性.
1.webpack 不在单独使用, 4.x 版本将很多命令移动到了 webpack-cli 包中. 若想要本地安装使用 webpack, 一般需要以下两步
(1) 全局安装 webpack,webpack-cli
(2) 局部安装 webpack,weback-cli
2. 增加了模式区分 (development,production):
开发者可通过 webpack --mode development/production 进行模式切换, 也可以通过在配置文件中添加 mode 配置项进行模式选择.
development: 开发模式, 打包默认不压缩代码, 默认开启代码调试
production: 生产模式, 上线时使用, 打包压缩代码, 不开启代码调试.
*** 若要开启代码调试可在配置文件中增加 devtool 配置项
devtool: "source-map" 3. 固定入口目录为 src, 与入口默认文件 index.js(webpack4.x 向简化配置方向发展的第一步).
当只有 src 目录与 src 目录下的 index.js 时, 无需增加 webpack.config.js,4.x 版本也会将打包后文件放至新增的 dist 目录下.
js 代码抽离时, 需在 config 中新增 optimization 配置项 (下面会详细说拆分代码的规则)
复制代码 optimization: { splitChunks: { cacheGroups: { vendor: { chunks: "initial", name: "jquery", enforce: true } } } } 复制代码 二, 4.x 版本个人习惯的项目目录结构如下图, 整个目录完全为动手搭建, 并非用脚手架修改而成.
三, 配置文件核心要点
(1) 当项目需要多文件入口时, 入口项需要以 json 的格式添加
复制代码 entry: { // 多入口文件 a: './src/js/index.js', b: './src/js/index2.js', jquery: 'jquery' } 复制代码 (2) 当多入口文件对应多出口文件时, 出口文件的 name 需要与入口项的 key 相对应
复制代码 output: { path:path.resolve(__dirname, 'dist'), // 打包多出口文件 // 生成 a.bundle.js b.bundle.js jquery.bundle.js filename: './js/[name].bundle.js' } 复制代码 (3) 多 html 文件需要 new 多个 htmlWebpackPlugin 实例
复制代码 // 自动生成 html 模板 new htmlWebpackPlugin({ filename: "index.html", title: "xxxx", chunks: ['a',"jquery"], // 按需引入对应名字的 js 文件 template: "./src/index.html" }), new htmlWebpackPlugin({ chunks: ['b'], filename: "index2.html", title: "page2", template: "./src/index2.html" }) 复制代码 (4) 按依赖提取 js 时, 4.x 版本写法与之前完全不同
复制代码 // 提取 js,lib1 名字可改 optimization: { splitChunks: { cacheGroups: { lib1: { chunks: "initial", name: "jquery", enforce: true } } } } 复制代码 在多页使用 webpack 时, 其实我们最头疼的或者需求最大的就是代码拆分问题. 代码是否拆分, 怎么拆, 什么情况下拆. 最新的 splitChunksPlugin 基本能满足我们的所有需求.
我在 webpack4.x 版本 splitChunksPlugin 的配置项详解与实际应用场景 中提到过, 最重要的就是 priority 这个属性. 下面具体说下我们的实际需要:
首先需要确定的是你是想优先匹配自己定义的拆分规则还是想优先匹配 webpack 默认的拆分规则, 若相匹配自己定义的拆分规则, 则 priority 需要设置为正数, 优先匹配默认拆分规则就设置为负数.
最终 webpack 会根据优先级进行打包 (从大到小, 从正数到负数).
(5) 引入第三方库时, 建议全局暴露. 这样在打包时, 4.x 会按需打包.
- // 全局暴露统一入口, 其他文件直接用就可以
- new webpack.ProvidePlugin({
- $: "jquery"
- }),
四, 下面附上三个主要的配置文件
1.webpack.config.js
复制代码 const path = require('path'); const pluginsConfig = require("./webpack.plguins.js"); const rulesConfig = require("./webpack.rules.js");
module.exports = { entry: { // 多入口文件 a: './src/js/index.js', b: './src/js/index2.js', jquery: 'jquery' }, output: { path:path.resolve(dirname, 'dist'), // 打包多出口文件 // 生成 a.bundle.js b.bundle.js jquery.bundle.js filename: './js/[name].bundle.js' }, plugins: pluginsConfig, devServer: { contentBase: path.resolve(dirname, "dist"), host: "localhost", port: "8090", open: true, // 开启浏览器 hot: true // 开启热更新 }, // devtool: "source-map", // 开启调试模式 module:{ rules: rulesConfig }, // 提取 js,lib1 名字可改 optimization: { splitChunks: { cacheGroups: { lib1: { chunks: "initial", name: "jquery", enforce: true } } } }
} 复制代码 2.webpack.plugins.js
复制代码 const webpack = require("webpack"); const path = require('path'); const glob = require("glob"); // 消除冗余的 CSS const purifyCssWebpack = require("purifycss-webpack"); // html 模板 const htmlWebpackPlugin = require("html-webpack-plugin"); // 清除目录等 const cleanWebpackPlugin = require("clean-webpack-plugin"); //4.x 之前用以压缩 const uglifyjsWebpackPlugin = require("uglifyjs-webpack-plugin"); // 分离 css const extractTextPlugin = require("extract-text-webpack-plugin"); // 静态资源输出 const copyWebpackPlugin = require("copy-webpack-plugin"); module.exports = [ new webpack.HotModuleReplacementPlugin(), // 调用之前先清除 new cleanWebpackPlugin(["dist"]), // 4.x 之前可用 uglifyjs-webpack-plugin 用以压缩文件, 4.x 可用 --mode 更改模式为 production 来压缩文件 // new uglifyjsWebpackPlugin(), new copyWebpackPlugin([{ from: path.resolve(dirname,"src/assets"), to: './pulic' }]), // 分离 css 插件参数为提取出去的路径 new extractTextPlugin("css/index.css"), // 消除冗余的 css 代码 new purifyCssWebpack({ // glob 为扫描模块, 使用其同步方法 paths: glob.sync(path.join(dirname, "src/*.html")) }), // 全局暴露统一入口 new webpack.ProvidePlugin({ $: "jquery" }), // 自动生成 html 模板 new htmlWebpackPlugin({ filename: "index.html", title: "xxxx", chunks: ['a',"jquery"], // 按需引入对应名字的 js 文件 template: "./src/index.html" }), new htmlWebpackPlugin({ chunks: ['b'], filename: "index2.html", title: "page2", template: "./src/index2.html" }) ] 复制代码 3.webpack.rules.js
复制代码 const extractTextPlugin = require("extract-text-webpack-plugin"); module.exports = [ { test: /.css$/, // 不分离的写法 // use: ["style-loader", "css-loader"] // 使用 postcss 不分离的写法 // use: ["style-loader", "css-loader", "postcss-loader"] // 此处为分离 css 的写法 /*use: extractTextPlugin.extract({ fallback: "style-loader", use: "css-loader", // css 中的基础路径 publicPath: "../"
- })*/
- // 此处为使用 postcss 分离 css 的写法
- use: extractTextPlugin.extract({
- fallback: "style-loader",
- use: ["css-loader", "postcss-loader"],
- // css 中的基础路径
- publicPath: "../"
- })
- },
- {
- test: /\.js$/,
- use: ["babel-loader"],
- // 不检查 node_modules 下的 js 文件
- exclude: "/node_modules/"
- },
- {
- test: /\.(png|jpg|gif)$/,
- use: [{
- // 需要下载 file-loader 和 url-loader
- loader: "url-loader",
- options: {
- limit: 50,
- // 图片文件输出的文件夹
- outputPath: "images"
- }
- }
- ]
- },
- {
- test: /\.html$/,
- // html 中的 img 标签
- use: ["html-withimg-loader"]
- },
- {
- test: /\.less$/,
- // 三个 loader 的顺序不能变
- // 不分离的写法
- // use: ["style-loader", "css-loader", "less-loader"]
- // 分离的写法
- use: extractTextPlugin.extract({
- fallback:"style-loader",
- use: ["css-loader", "less-loader"]
- })
- },
- {
- test: /\.(scss|sass)$/,
- // sass 不分离的写法, 顺序不能变
- // use: ["style-loader", "css-loader", "sass-loader"]
- // 分离的写法
- use: extractTextPlugin.extract({
- fallback:"style-loader",
- use: ["css-loader", "sass-loader"]
- })
- }
- ]
复制代码 *** 习惯用 webpack 之后, 会很方便. 不要怕出问题, 解决问题后的成就感会让你更加强大. github 上有本次 4.x 版本的 demo, 欢迎小伙伴提问题, 如果觉得还不错, 请给星!!
来源: http://www.qdfuns.com/article/36278/96193e97d9256e1075a29afeef5aac39.html