17 | 打包上线
Less 的打包涉及到三个 loader,如下:
- less-loader:用于将 Less 代码转换成 Css。
- css-loader:用于处理 Css 中的 import、url 等语句,以便能分析出图片等静态资源打包到最终结果。
- style-loader:会自动生成代码,并将打包后的 Css 插入到页面 style 标签。这个 loader 会将 Css 打包到 js 文件中,在应用运行时,自动生成的代码再把这些 css 应用到页面上。
其实背后的过程主要是,生成的 CSS 代码会以字符串的形式作为一个模块打包到最终结果,然后在运行时由 style-loader 提供的一个函数 injectStylesIntoStyleTag ,来将这个模块加入到页面的 style 标签中,从而最终生效。
实现提取 CSS 模块到单独 CSS 文件的 plugin 是 mini-css-extract-plugin
同时,通过刚才讲的例子,你应该也能看到 plugin 和 loader 的一个区别,就是 loader 主要用于处理不同类型的资源,将它们转换成模块;而 plugin 通常用于生成一些除了 JavaScript bundle 之外的一些打包结果,比如例子中的 index.html 和 css 文件。
| 单元测试
如何使用 Jest 和 React Testing Library 进行单元测试工欲善其事,必先利其器。要开始单元测试,要做的第一件事就是选择你的测试框架。
这其实包括两个部分的选择:
- 一个是通用的 JavaScript 测试框架,用于组织和运行你的测试用例;
- 另一个则是 React 的测试框架,用于在内存中渲染 React 组件并提供工具库用于验证测试的结果。
这两部分市面上其实都有挺多选择,比如通用的 JS 测试框架有 Mocha,Jasmine,Jest 等等;而测试 React 的框架有 Enzyme,Testing Library 等。
使用 React Testing Library 测试 React 组件我们可以先想一下,要对一个 React 组件进行单元测试,需要提供什么样的运行环境去运行测试用例呢?其实主要可以分为下面三点:
- 需要有一个浏览器运行环境。这个主要通过 jsdom 这样一个 npm 的模块去实现。它可以在 nodejs 环境中提供一个虚拟的浏览器环境,包括了几乎所有的浏览器 API,比如 document, window 等等,从而你的组件可以在内存中运行。
- 需要能够解析 JSX,以及项目中用到的最新的 JavaScript 语法 **。这是通过在 Jest 配置 Babel 去完成的。
- 需要能够方便地渲染一个 React 组件,并对结果进行验证。这正是 Testing Library 可以提供的功能。
可以直接测试 hooks
import { render, act } from '@testing-library/react';
import useCounter from './useCounter';
test('useCounter', () => {
const hookResult = {};
// 创建一个测试组件,仅运行 Hook,不产生任何 UI
const WrapperComponent = () => {
// 将 useCounter 的返回值复制给外部的 hookResult 对象
Object.assign(hookResult, useCounter());
return null;
};
// 渲染测试组件
render(<WrapperComponent />);
// 调用 hook 的 increment 方法
act(() => {
hookResult.increment();
});
// 验证结果为 1
expect(hookResult.count).toBe(1);
// 调用 hook 的 decrement 方法
act(() => {
hookResult.decrement();
});
// 验证结果为 0
expect(hookResult.count).toBe(0);
});
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('useCounter3', () => {
// 使用 renderHook API 来调用一个 Hook
const { result } = renderHook(() => useCounter());
// Hook 的返回值会存储在 result.current 中
// 调用加一方法
act(() => {
result.current.increment();
});
// 验证结果为 1
expect(result.current.count).toBe(1);
// 调用减一方法
act(() => {
result.current.decrement();
});
// 验证结果为 0
expect(result.current.count).toBe(0);
});
总结来说,只有对那些可重用的 Hooks,才需要单独的单元测试。
结语
“完成”和“认真完成”,在结果上有质的差别。
为什么 Facebook 要发明 React Hooks?React Hooks 解决了什么问题?
这个问题其实不难,但凡对 React Hooks 有点了解,都可以说出个所以然来。比如,让代码更简洁、让代码更易维护、让开发效率更高,等等。然而从这些回答中你会发现,这些候选人对 React Hooks 的理解还停留在表面,没有深入到本质。当然,如果你认真学完了我们这门课,答案其实也很简单:简化了逻辑重用。
只有不停的实践,提问才能学习,才能提升自己。
网友评论