一、console控制台打印vue的ref变量,如何更清楚一些?
二、 tree-shaking
true-shaking: 删除掉哪些? 函数执行没有副作用的,如果某个函数只是获取对象值,那也不能随便删除掉,因为有可能是Proxy对象,在执行get的时候有可能做了别的操作。
vue3源码中:
export const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS)
当然,该注释不仅仅作用于 函数,它可以应用于任何语句上。该注释也不是只有 rollup.js 才能识 别,webpack 以及压缩工具(如 terser)都能识别它。
三、框架应该输出怎样的构建产物
3.1 根据环境:
vue.global.js 用于开发环境,它包含必要的警告信息,而 vue.global.prod.js 用于生产环境,不包含警告信息。
3.2 根据使用场景:
- 标签引入, 我们需要输出一种叫作 IIFE 格式的资源。 IIFE 的全称是 Immediately Invoked Function Expression,即“立即调用的 函数表达式”,易于用 JavaScript 来表达:实际上, vue.global.js 文件就是 IIFE 形式的资源
(function () { // ... }())
- ESM 格式的资源, 两种: 用于 浏览器的 esm-browser.js 和用于打包工具的 esm-bundler.js。前者直接将 DEV 常量替换 为字面量 true 或 false,后者则将 DEV 常量替换为 process.env.NODE_ENV !== 'production' 语句。
<script type="module" src=""/path/to/vue.esm-browser.js"></script>
- CommonJS
四、开关特性
// webpack.DefinePlugin 插件配置
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: JSON.stringify(true) // 开启特性
})
vue编写代码中,如果明确知道自己不会使用选项 API,用户就可以使 用 VUE_OPTIONS_API 开关来关闭该特性,这样在打包的时候 Vue.js 的这部分代码就不会包含在最终的资源中,从而减小资源体积。
五、错误处理
// utils.js
let handleError = null
03 export default {
04 foo(fn) {
05 callWithErrorHandling(fn)
06 },
07 // 用户可以调用该函数注册统一的错误处理函数
08 registerErrorHandler(fn) {
09 handleError = fn
10 }
11 }
12 function callWithErrorHandling(fn) {
13 try {
14 fn && fn()
15 } catch (e) {
16 // 将捕获到的错误传递给用户的错误处理程序
17 handleError(e)
18 }
19 }
01 import utils from 'utils.js'
02 // 注册错误处理程序
03 utils.registerErrorHandler((e) => {
04 console.log(e)
05 })
06 utils.foo(() => {/*...*/})
07 utils.bar(() => {/*...*/})
六、良好的 Typescript 类型支持
并不是使用 TS 编写框架,就等价于对 TS 类型支持 友好,其实这是两件完全不同的事。
6.1 返回值类型丢失
01 function foo(val: any) {
02 return val // 无论参数传的什么值,返回值类型: any
03 }
// 期望传入什么类型,返回什么类型
01 function foo(val: T): T {
02 return val
03 }
Vue.js 源码中的 runtimecore/src/apiDefineComponent.ts 文件,整个文件里真正会在浏览器中运 行的代码其实只有 3 行,但是全部的代码接近 200 行,其实这些代码 都是在为类型支持服务。由此可见,框架想要做到完善的类型支持, 需要付出相当大的努力。