第2章 夹具工程初始化与环境搭建

本章正式进入工程化环节,你将完成 Material 3 组件夹具的开发环境搭建。我们同时提供 Vite + React 和 Next.js 两种主流方案,并统一加入 TypeScript 严格模式、ESLint 代码规范以及 M3 官方依赖。最终输出一个可直接运行的验证工程,为后续所有章节的组件封装与测试夹具提供一致的基线。

2.1 构建工具选型对比

根据项目需求选择合适的构建工具。对于组件夹具库,Vite 的轻量开发服务器和极速 HMR 更适配;若夹具需要集成到现有 Next.js 项目中,则选择后者。下表列出关键差异:

维度Vite + ReactNext.js 14+
启动速度秒级(ESM native)中等(需要预编译)
路由支持需额外安装 react-router内置文件系统路由
SSR/SSG无全套服务端渲染
M3 集成难度直接使用 Web Components需关闭 SSR 或使用 dynamic import
推荐场景纯组件夹具库
独立演示页面
全栈应用 + 夹具演示

2.2 项目初始化(Vite 方案)

执行以下命令创建 Vite + React + TypeScript 项目:

npm create vite@latest m3-fixtures -- --template react-ts
cd m3-fixtures
npm install

若选择 Next.js:

npx create-next-app@latest m3-fixtures --typescript --eslint
cd m3-fixtures

2.3 安装 Material 3 依赖

Google 官方 M3 Web 组件库 @material/web 是唯一官方依赖。它基于 Lit 构建,可在任何框架中使用。安装命令:

npm install @material/web

同时建议安装 react 和 react-dom 的类型声明(Vite 模板已包含)。若你使用 React 封装 Web Components,无需额外适配器,直接导入组件标签即可。

💡 提示:@material/web 包含 50+ 组件,无需逐个安装。项目中只需 import 所需组件样式或注册组件。

2.4 TypeScript 严格模式配置

编辑 tsconfig.json,确保严格模式开启并添加路径别名:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    "jsx": "react-jsx",
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "noEmit": true
  },
  "include": ["src"]
}

关键项说明:

  • strict: true —— 开启所有严格类型检查,杜绝隐式 any。
  • noUncheckedIndexedAccess —— 防止数组/对象索引未定义访问。
  • paths —— 配合 Vite 的 resolve.alias,实现 @/ 导入。

2.5 ESLint 配置

Vite 模板已内置 eslint 与 typescript-eslint。额外安装 React Hooks 规则和 import 排序:

npm install -D eslint-plugin-react-hooks eslint-plugin-import

在项目根目录创建 eslint.config.js(Flat Config 格式):

import js from "@eslint/js";
import tseslint from "typescript-eslint";
import reactHooks from "eslint-plugin-react-hooks";
import importPlugin from "eslint-plugin-import";

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommended,
  {
    plugins: {
      "react-hooks": reactHooks,
      import: importPlugin,
    },
    rules: {
      "react-hooks/rules-of-hooks": "error",
      "react-hooks/exhaustive-deps": "warn",
      "import/order": ["warn", { alphabetize: { order: "asc" } }],
      "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
    },
  }
);
⚠️ 注意:ESLint 9+ 默认使用 Flat Config(eslint.config.js),旧版 .eslintrc 不再推荐。若使用 Next.js 14,保留项目自动生成的配置即可。

2.6 验证:渲染一个 M3 按钮

在 src/App.tsx 中导入并使用 @material/web 的按钮组件:

import "@material/web/button/filled-button.js";
import "@material/web/button/outlined-button.js";

function App() {
  return (
    
主要操作 次要操作
); } export default App;

运行开发服务器:

npm run dev

浏览器中应显示两个 Material 3 按钮,带有涟漪动画和形态主题色。

2.7 环境搭建流程图

下图展示了从零到验证的完整初始化流程:

M3 夹具工程初始化流程 1. 构建工具选型 2. 创建项目 3. 安装 M3 依赖 4. TypeScript 配置 5. ESLint 配置 6. 验证按钮组件 7. 运行开发服务器 📌 关键验证点 • TypeScript 编译无错误(tsc --noEmit) • ESLint 不报 error(npm run lint) • 浏览器渲染 M3 按钮,无控制台警告

2.8 常见错误排查

问题原因解决方案
npm install 卡死网络代理或 registry 问题设置 npm config set registry https://registry.npmmirror.com
TypeScript 提示 "Cannot find module '@material/web'"未安装或路径别名冲突确认 import 路径为 @material/web/button/...,检查 node_modules 存在
ESLint 报 "React Hook useXXX" 规则未定义缺少 react-hooks 插件安装 eslint-plugin-react-hooks 并启用 rules
按钮无涟漪动画未加载 Web Components polyfill在入口文件添加 import '@material/web/button/filled-button.js'(已包含 polyfill)
Next.js 报错 "document is not defined"Web Components 在 SSR 环境下运行动态加载组件:const MdButton = dynamic(() => import('@material/web/button/filled-button.js'), { ssr: false })

2.9 性能与稳定性建议

  • 依赖锁定:使用 package-lock.json 或 pnpm-lock.yaml 锁定版本,避免队友或 CI 环境安装不同版本导致组件行为差异。
  • 按需加载:只 import 实际使用的 M3 组件 JS 文件,而非全量导入 @material/web/all.js,减少 bundle 体积。
  • TypeScript 增量构建:在 tsconfig.json 中开启 "incremental": true 加速二次编译。
  • ESLint 缓存:在 lint 命令后添加 --cache,避免重复检查未变更文件。