# 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 官网