webpackclassD
// source : 源代码与打包代码的关系映射关系
src
源代码
dist
打包后的代码
在webpack.config.js 中增加配置, 可以看到打包前的代码
可以看到报错代码的出现的位置
dist 目录中将增加一个目录, 这个目录显示, 打包后的文件和原来的文件的映射关系
devtool: "sourcemap",
dist会增加一个map文件,展示源文件和打包后的文件的映射关系
main-2bdbff02.js.map
devtool: 'inline-source'
仍然存在映射关系, 存在打包后的main.js 中, 在最下面
devtool: 'none'
不开启, 构建速度最快, 重构速度也快
两个重要的指标
eval: 使用eval 对代码进行包裹,cheap : 订阅错误精确到多少行,不需要多少列, inline : 隐藏打包后的独立文件,放在bundle 文件中 module 也关心第三方关系loader(babel-loader),问题时候, hidden 隐藏
开发环境,可以使用 eval , eval -cheap-module-socuremap
生产环境: 推荐使用none , 不暴露源码, 也,可以使用hidden-sourcemap, 无法查看打包文件和源文件的注释,开启sourcemap 可以查看错误更细, 可以借助图片发送
生产环境, 线上监控系统的使用, 收集报错信息的位置,什么错误,提供给监控后台
webpack-dev-server
提升本地开发效率的神器
npm install [email protected] -D
本地启动服务的依赖
热更新, 自动打包更新,本地数据mock,自动打开游览器, 代理
package.json 文件中script 中配置
"server": "webpack-dev-server",
npm run server
自动接管webpack
常见的功能
mock 数据,
根目录下, 定义server.js 文件, 使用 express , express 相对于koa , 不需要使用中间件, 可以直接使用
server.js 文件
const express = require("express");
const app = express();
app.get("/api/info", (req, res) => {
res.json({
name: "webpack",
});
});
app.listen("9092", () => {
console.log('服务已经启动')
});
定义服务
服务启动, node server.js 启动服务, 游览器地址栏输入 localhost:9092/api/info 可以直接启动 服务
正常使用会有跨域问题
npm install axios -S
安装axios
使用axios 发送请求
import axios from 'axios';
axios.get('/api/info').then(res => {
console.log(res);
});
webpack devServer 只能服务开发环境,自己获取数据
打包后的代码,存放在 内存中,无法查看
devServer 在webpack.config.js 中的配置项
devServer: {
contentBase: "./dist", // 访问服务的地址
port: 8080, // 端口号定义, 打开页面的端口, 不是
open: true, // 是否自动游览器配置, 是否自动打开游览器的服务
proxy: { // 代理
"/api": { // 请求的地址上带有api 时, 将转化到其他接口上
target: "http://localhost:9092/", // 替换host和端口, 服务于开发环境
},
},
},
只适合开发环境, 获取打包后的文件
会将dist 目录下的所有文件清空, 保存在内存中, 就是一口砖
还可以直接访问css 文件, asserts 对应的目录
// 部门-ued-前端开发-购物车业务线-本职
子主题 1
另外一个项目-整合资源-成立工作室
有多少个页面, 布局是什么样的,有什么样的难点, 之前写的代码可以复用, 有多少可以自己写, 这个项目需要接口, 对接服务器,
babel 工具
babel 工具, 处理js 很强大, babel 是一个js的编译器
es6+ ts, jsx, flow 语法都需要babel
babel 现在的版本为7+
babel 编译js 的, 对js的语法支持非常好,webpack 默认支持js, json 模块
目标游览器环境
// flow -> js
// jsx -js
// ts -js
// es6+ -js
babel 也是一个平台,使用插件实现js转换, 类似乎postcss 一样
babel 中的预设插件 Presets, 专门用于js 转换的插件
Preset 中有四个单位, 分别处理不同的实现
@babel/preset-env : 处理javasctipt @babel/preset-flow 处理flow 语法 @babel/preset-react 处理react 语法 @babel/preset-typescript : 处理typescript
首先安装babel, babel-loader
npm install babel-loader @babel/core -D
版本7中的所有的babel 都归纳在@babel 中,我们需要的babel 就是@babel/core
在package.json 中对js 使用babel
在modules 中增加配置
{
test: /\.js$/,
use: {
loader: "babel-loader",
},
},
使用preset-env
处理js的转换
安装 preset-env
npm install @babel/preset-env -D
const 转换为 var 箭头函数转化为普通的函数
Es6 的 兼容特性还是不支持, promise 还是不支持, 转换为
可以使用pollfill 就是一个垫片的意思
包含ecma 新特性的一个库
babel7 不推荐使用stage-1
Tc39 流程
设想 , 只是一个想法
stage0
建议 值得跟进
stage 1
草案 初始规范
stage 3
候选 完成规范, 并在游览器上初步实现
stage 3
完成, 将在下一个年度版本完成
stage 4
pollfill 安装
npm install @babel/polyfill -S
生产依赖
使用
在原来的 promise 文件的头部,引入 import "@babel/polyfill"
打包后,体积变大
优化方式, 按需加载, 现在只需要promise
npm install core-js -D
自己安装的时候,为 3.8.1 版本时
用户使用 3.x版本时
用户想使用 3.x的情况时
如果使用polyfill
1 用户需要手动安装另外两个包
2 还需手动导入两个包 import 'core-js/stable'; import 'regenerator-runtime/runtime'; 两个包
导入比较麻烦
babel 的配置文件使用
在根目录生成.babelrc 文件
package.json 中的设置
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
// presets 具有四个插件
presets: ['@babel/preset-env'] // 使用preset-env 转换js
/*
presets: [['@babel/preset-env', { // 需要配置 preset-env , 所以使用数组嵌套数组
targets: { // 设置目标游览器环境
edge: "17",
chrome: '67'
},
corejs: 2, 不推荐使用polyfill
polyfill 依赖于 core.js , 依赖的版本为 ^2.6.5 固定死了
如果自己安装
core.js 分 2.x 版本, 与 3.x 版本
2.x版本新特性比3.x 版本的新特性少
useBuiltIns: 'useage' //
entry, 需要在webpack 入口文件 里 @babel/polyfill 一次
babel 会根据你的使用情况, 倒入垫片, 没有使用的功能 不会导入相关的垫片
useage: 不需要import 会自动检测, 但是需要安装@babl/polyfill
false 默认值 ,如果你 import '@babel/polyfill' 它也不会排除没有使用的垫片, 程序提价比较庞大
entr与usage 与效果相同, 但打包原理不同, entry 的打包体积更大
usage babel 7 的功能
}]] // 使用preset-env 转换js
*/
}
},
},
package.json 修改
{
test: /\.js$/,
use: {
loader: "babel-loader"
}
},
.babelrc 配置
{ // 可以使用字符串,也可以使用数组
"presets": [ // 默认的插件
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"chrome": "67"
},
"corejs": 2, //不推荐使用polyfill
// 在可以使用'corejs': 设置为3, 到需要额外安装 npm install core-js
// 使用3 的版本时, 打包的体积额外大,没有设置好
// 可以推荐使用2 , 因为现在使用的新特性不是很多, 期待更高的性能
"useBuiltIns": "usage"
}
],
"@babel/preset-react"
]
}
babel.config.js 是babel 6 的配置文件, .babelrc 配置文件
如何使用react
安装 @babel/preset-react 插件
npm install @babel/preset-react
就可以集成 react
使用 preset/typescript
集成typescript
集成vue
npm install vue-loader vue-template-compiler -D
在webpack 中集成vue
在module 中 配置vue-loader的使用 test: /\.vue$/, use: 'vue-loader'
loader 配置
使用 插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')
plugins: [ new VueLoaderPlugin()]
如何编写一个plugin
webpack 在编译的过程中,存在一个生命周期的概念, 在那个阶段自动做事情
1 启动webpack
2 获取配置信息; plugin ,中已经进行了实例化, 插件告知webpack 运行到哪一个阶段处理一些事情
webpack 的打包流程
// 获取webpack
const webpack = require("webpack");
// 位置信息
const options = require("../webpack.config.js");
// 返回一个对象
const compiler = webpack(options); // 传递配置信息
// 具有comiler.hooks 阶段
//compiler.hooks // 关系d
// hooks 遍历
Object.keys(compiler.hooks).forEach((hookName) => {
// hookName 每一个钩子的名称, 获取每一个钩子
if (compiler.hooks[hookName].tap) {
// 注册每一个钩子的执行函数, 增加回调函数
compiler.hooks[hookName].tap("anyString", () => {
console.log(`run -> ${hookName}`);
});
}
});
// 执行打包, 触发webpack 的编译流程
compiler.run();
Compiler Hooks
// 插件的结构
// 生成一个 text 文档结构
module.exports = class txtwebpackplugin {
// apply
apply(compiler) { // 最核心的函数, webpack 接受参数options 产生 compiler
// 钩子分两类,同步的钩子, 异步的钩子
//钩入hook, 注册钩子, 在emit 阶段进行注册
// 事件注册compiler.hooks.emit.tapAsync("txtwebpackplugin", (compilation, cb) => {
// 同步的钩子通过 tap 触发
// 异步的钩子痛殴 tapAsync 触发, 其实是注册对应的事件
console.log(compilation.assets); // 资源列表
// compilation
// cb 回调函数
// compilation.assets webpack 最后打包存放在dist 目录下
// 的文件对象,
compilation.assets["kkb.txt"] = { // 文件的名称
source: function () { // 文件的内容
return "hello txt";
},
size: function () { // 文件的大小
return 1; // 推荐设置
// 资源列表展示
},
};
cb(); // 下一个回调函数, 继续调用
});
// 同步的钩子 , 的注册 事件的名称
compiler.hooks.compile.tap("txtwebpackplugin", (compilation) => {
// console.log(compilation.assets);
// 没有回调函数
});
}
};
/*
原材料: 源代码
webpack 工厂处理
流水线 ---1, ----2, ---3---4 --emit
*/
Compiler Hooks
Compiler 编译器模块是创建编译实例的引擎, 大多数面向用户的插件都是首先在Compiler 上注册, Compiler 上暴露的一些常用的钩子
钩子: run : 类型: AsyncSeriesHook, 什么时候调用: 在编译器开始读取记录前执行
钩子: compile : 类型:SyncHook, 在一个新的compilation 创建之前执行
钩子: compilation : 类型:SyncHook, 什么时候调用: 在一次compilation 创建后执行插件
钩子: make : 类型: AsyncSeriesHook, 完成一次编译之前执行
钩子: emit : 类型: AsyncSeriesHook, 在生成文件到output目录之前执行,回调参数 compilation
钩子: afterEmit : 类型: AsyncSeriesHook, 什么时候调用: 在生成文件到output目录之后执行
钩子: assetEmitted : 类型: AsyncSeriesHook, 什么时候调用: 生成文件的时候u执行, 提供访问产出文件信息的入口, 回调函数参数: file, info
钩子: done : 类型: AsyncSeriesHook, 什么时候调用: 一次编译完成后执行, 回调参数: stats
自由主题
自由主题
Copy the code