ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

guess 项目中的 Create React App 样板工程:react-app Fixture 开发与构建实践指南

guess 项目中的 Create React App 样板工程:react-app Fixture 开发与构建实践指南 前端开发工具【免费下载链接】guess Libraries tools for enabling Machine Learning driven user-experiences on the web项目地址https://gitcode.com/gh_mirrors/gu/guess点击查看免费下载本篇技术指南以 packages/guess-parser/test/fixtures/react-app/README.md 为主体剖析 guess 仓库中作为路由解析测试样例的 Create React App 样板工程从目录结构、可用脚本、环境变量到代码分割、测试、部署的完整实操流程。读完本文你将理解 react-app fixture 的工程全貌掌握 CRA 工程的日常开发与生产发布要点并知晓它与 guess-parser 中 React JSX 路由解析能力的配合关系。在 guess 仓库中react-app 是一个由 Create React AppCRA脚手架生成的 React 示例工程被 guess-parser 用作静态路由解析的测试夹具fixture。它的package.json依赖react ^16.3.2、react-router ^4.2.0、react-loadable ^5.3.1与react-scripts 1.1.4脚本则直接沿用 CRA 的四件套start、build、test、eject。因此这份 README 实际就是 CRA 官方模板文档它完整定义了该 fixture 的构建、测试与部署约定也直接决定了 guess-parser 能从中解析出哪些路由。工程结构与构建入口CRA 对工程目录有强制约定public/index.html是页面模板src/index.js是 JavaScript 入口这两个文件必须存在且保持确切文件名其余文件可以删除或重命名。典型结构如下my-app/ README.md node_modules/ package.json public/ index.html favicon.ico src/ App.css App.js App.test.js index.css index.js logo.svg对照 react-app 的 src 目录src/index.js通过ReactDOM.render(App /, document.getElementById(root))挂载应用src/App.jsx定义路由与页面骨架public/index.html则提供挂载节点。文档特别强调Webpack 只处理src内的文件所有 JS 与 CSS 必须放在src下否则 Webpack 无法感知把文件放进src子目录能获得更快的增量重建。只有public内的文件可被public/index.html直接引用src之外的顶层目录如文档目录不会进入生产构建。这一约束正是 guess-parser 能够稳定解析路由的前提路由代码全部集中于src之下解析器只需遍历src目录即可捕获完整的Route声明见下文“路由解析的源码印证”。核心可用脚本在 react-app 目录下可运行四个脚本见 package.json脚本作用npm start启动开发模式默认打开http://localhost:3000代码改动自动刷新页面lint 错误同时显示在终端与控制台npm test启动 Jest 交互式监听测试模式npm run build生产构建输出到build目录React 以生产模式打包、代码被压缩且文件名带内容哈希可直接部署npm run eject一次性操作将 Webpack、Babel、ESLint 等配置与传递依赖复制进工程从此自行维护全部构建配置单向、不可回退其中eject是被文档反复提及的“最后手段”CRA 的精选特性集足以支撑中小型部署若只是调整少数选项更推荐使用环境变量或直接 forkreact-scripts见“替代 Eject 的方案”一节而不是把整个构建体系摊开到自己手里维护。支持的浏览器、语言特性与 Polyfill该模板默认使用最新版 React并支持“最新 JavaScript 标准的超集”除 ES6 语法外还支持指数运算符ES2016、async/awaitES2017、对象 rest/spread 属性stage 3、动态import()stage 3、类字段与静态属性stage 3以及 JSX 和 Flow 语法。文档特别强调内置 polyfill 只有三个Object.assign()—— 由object-assign提供Promise—— 由promise提供完整实现 Promises/Afetch()—— 由whatwg-fetch提供。这意味着若使用Array.from()、Symbol等需要运行时支持的 ES6 特性必须自行引入 polyfill 或确认目标浏览器已支持for...of等语法经 Babel 编译后也可能依赖 ES6 运行时必要时可用 Babel REPL 确认编译产物。目录与编辑器开发体验语法高亮与 Lint语法高亮按 Babel 官方编辑器配置文档为对应编辑器Sublime Text、Atom、VS Code 等启用 JSX/Babel 高亮。编辑器内 Lintreact-scripts0.2.0npm 3在工程根目录新建.eslintrc{ extends: react-app }即可让编辑器插件报告 lint 警告。注意.eslintrc的改动只影响编辑器集成不影响终端与浏览器内的 lint 输出——CRA 有意只提供一套最小规则集。若想统一代码风格文档建议使用 Prettier 而非扩展 ESLint 风格规则。编辑器内调试VS Code / WebStormVS Code 需要安装 Chrome Debugger 扩展并在.vscode/launch.json中加入{ version: 0.2.0, configurations: [{ name: Chrome, type: chrome, request: launch, url: http://localhost:3000, webRoot: ${workspaceRoot}/src, sourceMapPathOverrides: { webpack:///src/*: ${webRoot}/* } }] }若通过HOST/PORT环境变量调整过服务地址需同步修改url。随后npm start启动应用按F5即可在编辑器内断点调试。WebStorm 则在Run - Edit Configurations...中新增JavaScript DebugURL 填http://localhost:3000macOS 按^D、Windows/Linux 按F9启动调试。Prettier 自动格式化安装husky lint-staged prettier或yarn add三件套在package.json的scripts中新增precommit: lint-staged并添加lint-staged字段lint-staged: { src/**/*.{js,jsx,json,css}: [ prettier --single-quote --write, git add ] }此后每次提交前 Prettier 会自动格式化暂存文件首次全量格式化可运行./node_modules/.bin/prettier --single-quote --write src/**/*.{js,jsx,json,css}。日常开发操作清单安装依赖与导入组件安装任意依赖如 React Router使用npm install --save react-router # 或 yarn add react-router项目经 Babel 支持 ES6 模块。文档建议模块只导出单个对象如一个组件时用export default配import Button from ./Button工具模块导出多个函数时用命名导出导入时记得加花括号。代码分割Code SplittingCRA 通过动态import()支持代码分割——import()返回 Promise解析为模块的命名空间对象。例如App.js中点击按钮后再加载moduleA.jsimport React, { Component } from react; class App extends Component { handleClick () { import(./moduleA) .then(({ moduleA }) { // Use moduleA }) .catch(err { // Handle failure }); }; render() { return ( div button onClick{this.handleClick}Load/button /div ); } } export default App;moduleA.js及其独有依赖会被打成独立 chunk用户点击后才加载同样支持async/await写法。这正是 react-app fixture 的核心用途它的路由组件大量使用动态 import。在 src/App.jsx 中/intro与/main路由分别通过AsyncComponent(() import(./intro/Intro))和AsyncComponent(() import(./main/Main))懒加载src/main/Main.jsx 中/main/parent也走AsyncComponent(() import(./parent/Parent))而/main/kid则直接引入静态组件Kid。AsyncComponent由 src/LazyRoute.jsx 基于react-loadable封装负责渲染加载中/出错/完成三态。这种“静态路由 懒加载组件”的混合形态正是 guess-parser 用来验证“既能识别路由路径、又能标记哪些路由是懒加载”的典型样本。样式与静态资源样式在 JS 中import ./Button.css声明依赖Webpack 在开发模式下热更新样式生产构建时将所有 CSS 合并压缩为单个文件。CSS 后处理Autoprefixer 自动压缩并添加厂商前缀如display: flex会生成-webkit-box/-ms-flexbox前缀版本。CSS 预处理器以 Sass 为例安装node-sass-chokidar后新增脚本build-css: node-sass-chokidar src/ -o src/, watch-css: npm run build-css node-sass-chokidar src/ -o src/ --watch --recursive借助--include-path可免相对路径导入import styles/_colors.scss、import nprogress/nprogress。用npm-run-all -p watch-css start-js可并行跑 Sass 监听与 dev server。文档选用node-sass-chokidar是因为node-sass --watch在虚拟机/Docker 下有性能问题、存在无限编译与文件监听失效的缺陷。图片/字体/文件在 JS 中import logo from ./logo.png导入结果即最终 URL小于 10,000 字节的 bmp/gif/jpg/jpeg/png 会内联为 data URISVG 除外CSS 中url(./logo.png)同样会被 Webpack 解析。生产文件名由内容哈希生成内容变化会自动换名无需担心缓存。public文件夹的使用public下的文件不会被 Webpack 处理而是原样复制进build。引用它们需使用%PUBLIC_URL%HTML 中或process.env.PUBLIC_URLJS 中link relshortcut icon href%PUBLIC_URL%/favicon.icoreturn img src{process.env.PUBLIC_URL /img/logo.png} /;其代价是文件不做后处理/压缩、缺失文件不会在编译期报错用户会得到 404、文件名不含哈希变更需手动改名或加查询参数。文档建议仅在少数场景使用需要特定文件名如manifest.webmanifest、海量图片需动态引用路径、引入无法被 Webpack 打包的小脚本或第三方库script。若在 HTML 中声明全局变量JS 侧应显式const $ window.$;读取避免 lint 报错。环境变量环境变量在构建时注入CRA 产出静态包无法在运行时读取。除内置的NODE_ENV外自定义变量必须以REACT_APP_开头否则会被忽略防止意外暴露机器上同名私钥。npm start/npm test/npm run build下NODE_ENV分别恒为development/test/production且不可手动覆盖。代码中通过process.env.REACT_APP_SECRET_CODE读取HTML 中通过%REACT_APP_WEBSITE_NAME%占位。临时变量按平台设置:: Windows cmd.exe set REACT_APP_SECRET_CODEabcdef npm start# Windows Powershell ($env:REACT_APP_SECRET_CODE abcdef) -and (npm start)# Linux/macOS Bash REACT_APP_SECRET_CODEabcdef npm start永久变量写入工程根目录的.env建议纳入版本控制排除.env*.local。.env文件族按优先级加载npm start为.env.development.local、.env.development、.env.local、.envnpm run build为.env.production.local、.env.production、.env.local、.envnpm test为.env.test.local、.env.test、.env注意无.env.local。.env内还支持变量展开REACT_APP_VERSION$npm_package_version。开发期代理 API前后端同源部署时可在package.json加proxy: http://localhost:4000开发服务器会把不带text/html的未知请求转发到该地址绕开 CORS。若默认代理不够灵活可用对象形式并支持正则匹配路径proxy: { /api: { target: url, ws: true }, /foo: { target: url_2, ssl: true, pathRewrite: { ^/foo: /foo/beta } }, /bar/[^/]*[.]html: { target: url_3 } }对象形式的代理对所有匹配请求含text/html一律生效。WebSocket 代理需ws: true且 Socket.io 只能代理到 Socket.io 服务器。启用代理后若遇 “Invalid Host header”DNS 重绑定防护可设置HOST或不推荐地在.env.development.local中写DANGEROUSLY_DISABLE_HOST_CHECKtrue。开发期 HTTPS设置HTTPStrue后npm startset HTTPStruenpm start或HTTPStrue npm start服务器会使用自签名证书浏览器会提示警告此特性常用于配合代理访问 HTTPS 的 API 服务器。服务端注入与预渲染动态 meta 标签CRA 不支持服务端渲染可在index.html中留占位符如meta propertyog:title content__OG_TITLE__服务器读取 HTML 后按当前 URL 替换务必转义、消毒插入值。预渲染静态 HTML用react-snapshot或react-snap为每个路由生成 HTML 页面JS bundle 加载后自动“水合”hydrate。收益是核心内容随 HTML 到达且更易被搜索引擎收录。服务端注入数据在 HTML 中留window.SERVER_DATA __SERVER_DATA__;服务器发送响应前替换为真实 JSON务必先消毒 JSON 再下发否则存在 XSS 风险。测试体系Jest jsdomCRA 使用 Jest 作为测试运行器测试在 Node 环境配合 jsdom 模拟浏览器全局运行速度快、不易抖动定位为逻辑与组件单测而非 DOM 行为测试端到端测试建议另用专用工具。命名约定与交互式 CLIJest 会识别三种命名约定__tests__目录下的.js文件、*.test.js、*.spec.js可位于src下任意深度。文档建议把测试文件与被测代码放同一目录缩短相对导入路径。npm test进入 watch 模式保存文件即重跑交互式 CLI 支持按搜索模式聚焦测试watch 模式下默认只跑自上次提交以来变更文件相关的测试按a可强制全量运行CI 或非 git 仓库中则默认全量。编写测试用内置expect()断言、jest.fn()做间谍。组件“冒烟测试”示例import React from react; import ReactDOM from react-dom; import App from ./App; it(renders without crashing, () { const div document.createElement(div); ReactDOM.render(App /, div); });隔离渲染可用 Enzyme安装enzyme enzyme-adapter-react-16 react-test-renderer并在src/setupTests.js中configure({ adapter: new Adapter() })随后可用shallow(App /)浅渲染不深入子组件与mount()完整渲染适合测状态与生命周期。src/setupTests.js还会在每轮测试前自动执行可在此注入全局 mock如localStorage。xit()排除测试、fit()聚焦测试npm test -- --coverage产出覆盖率报告package.json的jest字段可覆盖collectCoverageFrom、coverageReporters、coverageThreshold、snapshotSerializers。CI 与调试设置CItrue后npm test只跑一轮并退出不再进入 watchernpm run build将 lint 警告视为构建失败。Travis CI 的.travis.yml示例language: node_js node_js: - 6 cache: directories: - node_modules script: - npm run build - npm test若测试不依赖 jsdom可去掉test脚本的--envjsdom以提速window/document、ReactDOM.render()、mount()需要 jsdom而TestUtils.createRenderer()、shallow()与快照测试不需要。Chrome 调试测试需 Node 8添加test:debug: react-scripts --inspect-brk test --runInBand --envjsdom脚本后打开about:inspect附加调试器VS Code 则可用launch.json中type: noderuntimeExecutable: react-scripts的配置直接调试。生产构建与部署npm run build产出build目录静态服务器把index.html交给访问者、把/static/js/main.hash.js等路径映射到对应文件。最简方案是用servenpm install -g serve serve -s build默认端口 5000可用-p/--port调整serve -h查看全部选项也可集成进 Expressconst express require(express); const path require(path); const app express(); app.use(express.static(path.join(__dirname, build))); app.get(/, function (req, res) { res.sendFile(path.join(__dirname, build, index.html)); }); app.listen(9000);客户端路由pushState的服务器配置使用 React RouterbrowserHistory这类 HTML5pushState路由时静态服务器对/todos/42这类前端路由会 404必须把未知路径全部回退到index.html。Express 改为app.get(/*, ...)Apache 在public放.htaccessOptions -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.html [QSA,L]生产构建启用 service worker 后浏览器也会自动以缓存的index.html兜底导航请求可通过 eject 后调整navigateFallback、navigateFallbackWhitelist配置并建议把public/manifest.json的start_url改为.以配合客户端路由。相对路径构建默认构建假定应用托管在服务器根路径。指定homepage: http://mywebsite.com/relativepath可让 CRA 推断正确的资源根路径react-router^4用户还可给BrowserRouter basename/calendar设置 basename。若不用 pushState 客户端路由可设homepage: .使所有资源路径相对index.html同一构建即可迁移到任意子路径。各平台部署速览Firebasefirebase init选 Hostingpublic 目录填build、勾选单页应用务必在firebase.json的hosting.headers中给/service-worker.js配Cache-Control: no-cache否则首轮部署后难以看到更新随后firebase deploy。GitHub Pagespackage.json加homepage: https://myusername.github.io/my-app安装gh-pages并添加predeploy: npm run build、deploy: gh-pages -d build仓库设置中把 Pages 源切换为gh-pages分支。用户页需把部署推送到 mastergh-pages -b master -d build并让源分支不用 master。GitHub Pages 不支持 pushState 路由可改用 hashHistory 或借助404.html重定向技巧。Heroku使用 Heroku Buildpack for Create React App若构建失败注意 Linux 文件系统大小写敏感导致的 import 路径问题以及被.gitignore排除的必需文件。Netlify手动部署netlify deploy选build持续交付把构建命令设为yarn build、发布目录设为buildpushState 支持需在public/_redirects写/* /index.html 200。NowZeitnpm run build后进入build目录执行now --name your-project-name。S3/CloudFront、Surge、Azure均有对应接入方式Surge 支持 pushState 时可将index.html改名为200.html作为兜底。高级配置环境变量下表来自原文档的 Advanced Configuration 一节列出关键环境变量及其生效范围变量开发生产说明BROWSER✓✗默认打开系统浏览器macOS 偏好 Chrome设为none禁用或指定一个.js脚本自定义启动方式HOST✓✗默认绑定localhost可指定其他主机PORT✓✗默认尝试 3000 端口占用时提示下一个可用端口HTTPS✓✗设为true以 HTTPS 模式运行开发服务器PUBLIC_URL✗✓强制资源按给定 URL含主机名原样引用适合 CDN 托管CI◐✓构建时把警告视为失败测试运行器退出监听模式多数 CI 默认已设REACT_EDITOR✓✗覆盖崩溃 overlay 点击堆栈时自动检测的编辑器none禁用CHOKIDAR_USEPOLLING✓✗设为true启用轮询监听虚拟机内必要GENERATE_SOURCEMAP✗✓设为false关闭生产 source map缓解小内存机器 OOMNODE_PATH✓✓同 Node.jsNODE_PATH但仅允许相对目录可用于模拟 monorepo如NODE_PATHsrc常见故障排查npm start不感知变更从 Dropbox 目录移出工程编辑器“safe write”特性需关闭项目路径含括号时移动Webpack watcher 缺陷Linux/macOS 上调大 watcher 限额虚拟机内加CHOKIDAR_USEPOLLINGtrue。npm test在 macOS Sierra 挂起多为 Watchman 问题重装 Watchman 4.7.0brew reinstall watchman或直接卸载。npm run build提前退出内存不足含云环境无 swap建议加 swap 或本地构建。Moment.js 区域缺失默认仅含英文 locale需显式import moment/locale/fr;后moment.locale(fr)切换。npm run build压缩失败部分第三方包未预编译为 ES5可在依赖仓库提 issue、fork 修复或把小型依赖直接拷入src/当作应用代码处理。与 guess-parser 路由解析的源码印证react-app fixture 的价值远超“一个普通 CRA 示例”——它是 guess-parser 验证React JSX 路由解析的测试样例。react-jsx.spec.ts 直接调用parseReactJSXRoutes(packages/guess-parser/test/fixtures/react-app/src)断言解析结果恰为五个路由/、/intro、/main、/main/kid、/main/parent且非懒加载路由的路径为/main/kid。从源码结构看这一结果与上文读到的组件声明一一对应src/App.jsx 声明了Redirect from/ to/intro、/intro、/main三个顶层路由src/main/Main.jsx 声明了子路由/main/kid与/main/parentRoute的component属性要么是静态组件如Kid要么是AsyncComponent(() import(...))动态加载如/intro、/main、/main/parent解析器据此标记lazy属性。而 src/react/react-jsx.ts 的实现揭示了底层机制parseRoutes读取 fixture 的src下全部文件后以JsxEmit.ReactallowJs: true的 TypeScript 编译选项解析 JSX 文件。也就是说react-app 的 README 所描述的“动态import()代码分割”与“React Router 路由声明”正是 guess-parser 静态扫描 JSX 代码、重建站点路由图的输入样本该 fixture 的目录组织路由集中在src也与 README 中“Webpack 只处理src内文件”的约定互为表里。替代 Eject 的方案eject 后需长期自行维护配置成本高。文档建议与其 eject不如forkreact-scripts及所需依赖包按需修改这样多个项目可共享同一份定制脚本。若只是调整个别构建/环境选项优先使用上文“高级配置”中的环境变量而非把整个构建管线收入囊中。结语这份 CRA 模板 README 既是 react-app fixture 的开发运维手册也是理解 guess-parser React 路由解析能力的工程背景。从目录约定、四件套脚本、环境变量与代理到 Jest 测试、预渲染与多平台部署它覆盖了一个 CRA 工程从脚手架到上线的完整生命周期而在 guess 仓库中它更承担着“路由解析测试样本”的角色——README 描述的代码分割模式与路由声明方式正是 guess-parser 解析器逐文件扫描src、产出路由图与懒加载标记的真实数据来源。赞分享前端开发工具【免费下载链接】guess Libraries tools for enabling Machine Learning driven user-experiences on the web项目地址https://gitcode.com/gh_mirrors/gu/guess点击查看免费下载相关推荐PhoneInfoga 电话号码核验使用教程一条命令跨 5 个数据源交叉核对号码还能本地开 Web 界面PhoneInfoga 电话号码核验使用教程一条命令跨 5 个数据源交叉核对号码还能本地开 Web 界面 PhoneInfoga 是一个开源的电话号码信息收网络安全后端awesome-compose 实战React 前端Create React App开发、测试与构建全指南awesome compose 实战React 前端Create React App开发、测试与构建全指南 导读 本指南以 awesome compose示例工程Create React App 项目集成 React Styleguidist组件开发与实时样式指南的完整实操Create React App 项目集成 React Styleguidist组件开发与实时样式指南的完整实操 本篇指南以 React Styleguidi开发工具前端上一篇fs-extra 的 pathExists / pathExistsSync基于 fs.access 的路径存在性检测指南下一篇Humanizer 数值量级扩展方法用 Tens、Hundreds、Thousands、Millions、Billions 写出可读的数值常量创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表