# webpack_dev **Repository Path**: pipepandafeng/webpack_dev ## Basic Information - **Project Name**: webpack_dev - **Description**: 基于webpack的构建模板 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-08-08 - **Last Updated**: 2022-05-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: webpack, CSS, Nodejs, JavaScript, HTML ## README # 🌲 webpack > 官网:https://webpack.docschina.org ## 安装 > webpack && webpack-cli -D ## webpack 可以进行 0 配置 * 🔶 打包工具 -> 输出后的结果(支持 js 模块) * 🔶 打包 (支持我们的 js 的模块化) ## 手动配置 webpack * 🔵 默认配置文件的名字 webpack.config.js * 🔵 开发服务器参数配置 * 🔵HtmlWebpackPlugin 插件使用 ## 插件和模块 * 🟡`css` `loader` 解析@import 这种语法 * 🟡`style-loader` 把 css 插入到 head 的标签中 * 🟡`mini-css-extract-plugin` 将 css 从 js 中抽离出来,单独打包 * 🟡`less`, `less-loader`处理 less 文件 * 🟡`babel-loader` 处理 ES6 * 🟡`postcss-loader autoprefixer` 处理自动添加浏览器前缀 * 🟡`css-minimizer-webpack-plugin` 压缩 css && 在 `optimization.minimizer` 中可以使用 `'...'` 来访问默认值。防止 css 压缩后 js 又不压缩(js 是默认压缩的) ## 处理 js * 🟢 转义 JS 语法,将 ES 高级语法转换为浏览器 ES5 语法 需要用到的包: `@babel-loader` `@babel/core` `@babel/preset-env` * 🟢 处理 class `@babel/plugin-proposal-class-properties` ,装饰器语法 `@babel/plugin-proposal-decorators` * 🟢 在项目中使用了 async/await, 就开始报错 regeneratorRuntime is not defined。则需要处理 es7 语法,@babel/plugin-transform-runtime @babel/polyfill(已被废弃) * 🟢 校验 js eslint-loader enforce:pre ## 处理全局变量引入问题 > 作用:把变量暴露到全局 * 🔵 采用 `expose-loader` 可采用内联 loader 或 直接在 webpack.config.js 中配置。 ```js import $ from "expose-loader?exposes=$!jquery"; // 采用内联loader处理全局变量问题 ``` ``` module: { rules: [ { test: require.resolve("jquery"), loader: "expose-loader", options: { exposes: ["$", "jQuery"], } } ] } 其他使用方式可到npm上查看官网示例 ``` * 🔵 采用`webpack. ProvidePlugin`自动加载,在任何地方不必 import 或 require 模块。给每个模块注入一个$ ```js new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", }); ``` * 🔵 引入 CDN, 不打包的方式。采用`Externals` ```js module.exports = { //... externals: { /* import $ from "jquery"; 引号前面的是我们项目中引入的包名(可自定义) 例如:import $ from "jqueryTEST"; externals: { jqueryTEST: 'jQuery', } 引号后面的是CDN中暴露的全局变量 */ jquery: "jQuery", }, }; ``` ## 处理图片 * 🟣"url 处理图片和打包优化 > `url-loader` 内置了 `file-loader` , 是增强的 `file-loader` 。 > 优点: 如果图片较多,会发很多 http 请求,会降低页面性能。url-loader 会将引入的图片编码,生成 dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此 url-loader 提供了一个 limit 参数,小于 limit 字节的文件会被转为 DataURl,大于 limit 的还会使用 file-loader 进行 copy。 > 注意: `url-loader` 需要结合 `file-loader` 使用。 ```js /* 下载依赖 */ yarn add url - loader file - loader - D /* webpack.config.js配置 */ module: { rules: [{ test: /\.(png|jpg|gif)$/i, use: [{ loader: 'url-loader', options: { limit: 40960, // 超过40KB采用file-loader处理 } }] }] } /* 应用代码段 */ import shrimp from './images/shrimp.png'; let img = new Image() img.src = shrimp $('body').append(img); ``` ## 打包文件分类 > 将不同的文件类型打包到各自的文件夹中 * 🟤js 分类 ```js module.exports = { output: { filename: "js/[name].[contenthash:8].bundel.js", //采用contenthash,自己发生改变,只重新hash自己,不会hash真个项目。采用[hash]则会hash整个项目 path: path.resolve(__dirname, "dist"), }, }; ``` * 🟤css 分类 ```js module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: "css/main.[contenthash:8].css", }), ], }; ``` * 🟤image 分类 ```js module.exports = { module: { rules: [{ test: /\.(png|jpg|gif)$/i, use: [{ loader: "url-loader", options: { limit: 40960, outputPath: "img/", // fallback: require.resolve('image-webpack-loader') }, }, ], }, ], }, }; ``` ## 多页面打包配置 * ⚫ 多页面应用 webpack 打包配置 ```js // webpack.config.js module.exports = { entry: { ...你的配置... // 配置多入口 main: "./src/index.js", // 前面的key就是打包后的文件名 test: "./src/test.js", // 前面的key就是打包后的文件名 }, // new 多个HtmlWebpackPlugin插件 plugins: [ new HtmlWebpackPlugin({ template: "./src/index.html", //模板位置 filename: "index.html", //打包出来后的文件名 minify: { removeAttributeQuotes: true, //删除双引号 collapseWhitespace: true, }, hash: true, chunks: ["main"], // 只引入main模块 }), new HtmlWebpackPlugin({ template: "./src/home.html", //模板位置 filename: "home.html", //打包出来后的文件名 minify: { removeAttributeQuotes: true, //删除双引号 collapseWhitespace: true, }, hash: true, chunks: ["test"], // 只引入test模块 }), ] } ``` ## source-map 源码映射配置 * 🟥`dev-tool:'source-map'` > 产生一个单独的 source-map 文件,功能最完全,但会减慢打包速度 * 🟥`dev-tool:'eval-source-map'` > 使用 eval 打包源文件模块,直接在源文件中写入干净完整的 source-map,不影响构建速度,但影响执行速度和安全,建议开发环境中使用,生产阶段不要使用 * 🟥`dev-tool:'cheap-module-source-map'` > 会产生一个不带映射到列的单独的 map 文件,开发者工具就只能看到行,但无法对应到具体的列(符号),对调试不便 * 🟥`dev-tool:'cheap-module-eval-source-map'` > 不会产生单独的 map 文件,(与 eval-source-map 类似)但开发者工具就只能看到行,但无法对应到具体的列(符号),对调试不便 ```js module.exports = { /* 配置开发工具 */ devtool: "source-map", }; ``` ## watch 的用法 监控文件 * 🟧 监控文件,实时打包。(仅用于构建) ```js module.exports = { /* Do not use serve with --watch. serve already watches for changes. */ watch: true, // 生产环境不要开启此选项 Do not use serve with --watch. serve already watches for changes. watchOptions: { aggregateTimeout: 2000, //防抖 ignored: /node_modules/, //需要忽略的监听文件 poll: 1000, // // 每秒检查一次变动 }, }; ``` ## webpack 小插件 * 🟨`cleanWebpackPlugn` > 自动删除之前的构建包,避免构建包越来越大 * 🟨`copyWebpackPlugin` > 将已存在的单个文件或整个目录复制到构建目录。 * 🟨`bannerPlugin` webpack 内置插件 > 给打包后的 js 添加版权或者说明 ## webpack 代理配置 `http-proxy` * 🟩 配置 proxy 解决跨域 ```js module.exports = { //... devServer: { proxy: { context: ["/auth", "/api"], //如果想将多个特定路径代理到同一目标,则可以使用一个或多个带有 context 属性的对象的数组: "/api": "http://localhost:3000", pathRewrite: { "^/api": "", //不希望传递api 如果不设置此参数 所有请求将会携带/api 即:http://localhost:3000/api }, changeOrigin: true, // 默认情况下,代理时会保留主机头的来源,可以将 changeOrigin 设置为 true 以覆盖此行为。 }, }, }; ``` * 🟩mock 数据 ```js denServe: { before(app) { app.get('/user', (req, res) => { res.json({ name: 'pipe_before' }) }) } } ``` * 🟩 不用代理处理,服务端启动 webpack,保持本地端口一直,既解决了跨域问题 。 > 💚 在本地搭建项目既有服务端和客户端时非常有用 💚 ## resolve 解析配置 * module:[path.resolve('node_modules')] * extensions:['.js', '.json', '.wasm'], 解析后缀顺序 * mainFields * mainFiles 入口文件名字 index.js ```js module.exports = { resolve: { modules: [path.resolve(__dirname, "other_modules"), "node_modules"], //webpack 解析模块时应该按顺序搜索的目录 // mainFields: ['style'], //此选项将决定在 package.json 中使用哪个字段导入模块 extensions: [".css", "..."], alias: { bootstrap: path.resolve( __dirname, "node_modules/bootstrap/dist/css/bootstrap.css" ), // 创建 import 或 require 的别名,来确保模块引入变得更简单。 }, }, }; ``` ## 定义环境变量 > `webpack.definePlugin` 定义一个全局常量 ```js /* webpack.config.js */ new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), }); /* 代码中直接判断 */ if (!PRODUCTION) { console.log("Debug info"); } if (PRODUCTION) { console.log("Production log"); } /* 未经 webpack 压缩过的代码 */ if (!true) { console.log("Debug info"); } if (true) { console.log("Production log"); } /* 过压缩后 */ console.log("Production log"); ``` ## 区分不同环境 > `webpack-merge` 包 ```js let { smart } = require("webpack-merge"); let base = require("./webpack.config.my.js"); module.exports = smart(base, { mode: "development", devServer: {}, devtool: "source-map", }); ``` ## webpack 优化 > webpack 相关优化,请查看另一个仓库地址 https://gitee.com/pipepandafeng/webpack_opt ## 📰 资料 * 🚩webpack 学习视频 * 🚩webpack 官网