webpack学习总结

317 阅读4分钟

webpack.config.js

const path = require("path"); // node 内置模块
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 使用html模板
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // css文件单独压缩到独立的css文件中
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); // 压缩打包出来的css文件
const UglifyJsPlugin = reuqire("ugligyjs-webpack-plugin"); // 压缩打包出来的js文件, 默认js文件是压缩的,但是配置css压缩后js就不会再默认压缩,
const CleanWebpackPlugin = require("clean-webpack-plugin"); // 清除已打包文件
const CopyWebpackPlugin = require("copy-webpack-plugin"); // 拷贝文件夹
const Happypack = require("happypack"); // 多线程打包

module.exports = {
    mode: "development",
    entry: "./src.index.js",
    output: {
        filename: "bundle.[hash:8].js",
        path: path.resolve(__dirname, "dist"), // 必须是绝对路径
        publicPath: "" // 公共路径,所有资源引入时加上这个路径
    },
    // 增加映射文件,便于调测
    devtool: "source-map",
    // 启用监控
    watch: true,
    watchOptions: {
        poll: 1000, // 每秒更新多少次
        aggreateTimeout: 500, // 防抖, 一直输入时不触发
        ignored: /node-modules/ // 不需要监控的文件
    },
    // 打包优化项, 开发环境建议不用
    optimization: {
        // 压缩代码
        mininizer: [
            new UglifyJsPlugin({
                cache: true, // 启用缓存
                parallel: true, // 是否并发打包
                sourceMap: true
            }),
            new OptimizeCssAssetsWebpackPlugin()
        ],
        // 优化:抽离公共代码
        splitChunks: {
            cacheGroups: {
                // 公共模块
                common: {
                    chunks: "initial",
                    minSize: 0, // 文件大小
                    minChunks: 2 // 引用次数
                },
                // 第三方模块
                vernder: {
                    priority: 1, // 执行优先级:权重
                    test: /node_modules/,
                    chunks: "initial",
                    minSize: 0, // 文件大小
                    minChunks: 2 // 引用次数
                }
            }
        }
    },
    module: {
        npParse: /jQuery/, // 优化:不去解析的依赖
        rules: [
            {
                test: /\.less$/,
                // css-loader: 解析@import语法
                // style-loader: css插入到head标签中
                // less-loader: less转为css
                use: [
                    // "style-loader", // 插入到了header最下面,默认
                    MiniCssExtractPlugin.loader,
                    {
                        loader: "css-loader",
                        options: {}
                    },
                    {
                        loader: "less-loader"
                    },
                    "postcss-loader" // 自动补充css样式兼容性前缀, 配合autoperfixer包
                ] // 默认从右向左执行
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 优化:
                include: "/src",
                use: {
                    loader: "babel-loader", // 把js的es6语法转换为es5语法
                    options: {
                        // 预设成的语法包
                        presets: ["@babel/perset-env", "@babel/preset-react"], // @babel/preset-react 解析react
                        plugins: [
                            // 解决装饰器无法正确解析的问题
                            [
                                "@babel/plugin-proposal-decorators",
                                { legacy: true }
                            ],
                            // ES高级语法解析插件
                            [
                                "@babel/plugin-proposal-class-properties",
                                {
                                    loose: true
                                }
                            ],
                            // 解决工厂函数generator不能正确解析的问题: 抽离公共方法
                            "@babel/plugin-transform-runtime",
                            // 使用import 实现动态加载
                            "@babel/plugin-syntax-dynamic-import"
                        ]
                    }
                },
                include: path.resolve(__dirname, "src")
            },
            // js代码检测
            {
                use: /\.js$/,
                use: {
                    loader: "eslint-loader", // 注意此加载器的顺序
                    options: {
                        enforce: "pre" // 强制: 最先执行(pre) / post 之后执行
                    }
                }
            },
            // 模块暴露为全局
            {
                test: require.reaolve("jquery"),
                use: "expose-loader?$"
            },
            //引入图片
            {
                test: /\.(png|jpg|gif)$/,
                use: {
                    // 可以增加限制,满足条件转换为 base64 的图片, 不满足限制自动使用 file-loader
                    loader: "url-loader", //
                    options: {
                        limit: 200 * 1024,
                        outpurPath: "/images"
                    }
                }
            },
            // html文件 img 标签图片的引入
            {
                test: /\.html$/,
                use: "html-withimg-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./index.html",
            filename: "index.html",
            minify: {
                // 对html文件压缩处理
                removeAttributeQuotes: true, // 删除双引号
                collapseWhitespace: true // 折行显示
            },
            hash: true
        }),
        new MiniCssExtractPlugin({
            // 可以使用多个打包出多个css文件
            filenane: "/css/main.css"
        }),
        // 在每个模块中都注入$符
        new webpack.ProvidePlugin({
            $: "jquery"
        }),
        new CleanWebpackPlugin("./dist"), // 清空的文件夹
        new CopyWebpackPlugin([
            {
                from: "./src/assets",
                to: "./assets"
            }
        ]),
        //版权声明
        new webpack.BannerPlugin("版权声明内容 copyRight of my "),
        // 定义环境变量
        new webpack.DefinePlugin({
            DEV: JSON.stringify("development"), // 字符串
            FLAG: "true" // bool值
        }),
        // 优化:打包是不引入moment内部的locale的文件
        new webpack.IgnorePlugin(/\.\/locale/, /moment/),
        // 优化:先去此路径找依赖,没有再去打包依赖
        new webpack.DllReferencePlugin({
            manifest: path.resolve(__dirname, "dist", "manifest.json") // 任务清单
        }),
        // 热更新插件
        new webpack.HotModuleReplacementPlugin(),
        // 打印更新的模块路径
        new webpack.NamedModulesPlugin()
    ],
    // 配置不需要打包的模块
    externals: {},
    // 指定解析的第三方包的位置
    resolve: {
        modules: [path.resolve("node-modules"), path.resolve("")],
        // 设置路径别名
        alias: {
            "@": "./src"
        },
        mainFields: ["style", "main"], //入口文件顺序 package.json中查看文件类型
        mainFiles: ["index.js"], // 入口文件的名字
        extensions: [".js", ".css", ".json"] // 文件拓展名, 从左到右依次查找
    },
    devServer: {
        port: 3000,
        progress: true,
        contentBase: "./build", // 打包的静态文件保存的文件夹
        compress: true, // 启用压缩
        hot: true,
        // 配置代理
        proxy: {
            "/api": {
                target: "http://localhost:3001",
                pathRewrite: { "/api": "" } // 重写请求地址
            }
        },
        // 提供的钩子方法,直接起mock服务器
        before(app) {
            app.get("/api", (req, res) => {});
        }
    }
};

postcss.config.js

// 配置postcss-loader
module.exports = {
    plugins: [require("autoperfixer")]
};

webpack-dev-server + mockServer

const express = requrie("express");
const webpack = requyire("webpack");
const middle = requrie("webpack-dev-middleware");
const config = requrie("./webpack.config.js");
// http-proxy 服务器处理
const app = express();

// 使用打包后的资源, 使服务端和前端代码都起在服务端
let complier = webpack(config);
app.use(middle(complier));

app.get();

app.listen(3001);

安装

本地:webpack webpack-cli webpack-dev-server

@babel-polfill 解决无法正确解析更高级语法的问题

eslint 配置文件可通过官网自动生成

引入第三方模块的集中方法:

  • expose-loader: 暴露到 window 对象上;
  • providePlugin: 注入到每一个模块中
  • 全局引入,不打包

图片的引入

  • file-loader
  • html-withimg-loader // 引入 img 标签的图片
  • url-loader

devtool 可配置选项

  • source-map: 大和全,源码映射
  • eval-source-map: 不会产生单独的文件,但是可以显示行和列
  • cheap-module-source-map: 不会产生列但是会产生一个单独的映射文件
  • cheap-module-eval-source-map: 不会产生文件集成在打包后的文件中,也不会产生列

merge

module.exports = merge(common, {})

优化:

happypack 多线程打包: 大项目打包时使用

{ test: /.js$/, use: "Happypack/loader?id=js" }

new Happypack({ id: "js", use: [{ loader: "babel-loader", options: { presets: [ "@babel/presert-env", "@babel/preset-react" ] } }] })

production 模式下:

tree-shaking: 把没用到的代码自动删除掉 必须使用: import 的方法引入

scope hosting: 在 webpack 中自动忽略一些可以简化的代码

动态加载

@babel/plugin-syntax-dynamic-import
import("./app.js").then(data => {
data.default; // 获取数据
});

热更新

if(module.hot){
module.hot.accept("./dd.js", () => {
// 文件更新后执行
const data = require("./source").default;
});
}