ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Gatsby Slice API 云端构建优化实战:从 Slice 拆分解读到 Gatsby Cloud 90% 构建提速

Gatsby Slice API 云端构建优化实战:从 Slice 拆分解读到 Gatsby Cloud 90% 构建提速 Gatsby Slice API 云端构建优化实战从 Slice 拆分解读到 Gatsby Cloud 90% 构建提速【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby本指南以仓库中的 slices-optimization.md 为骨架系统讲解 Gatsby 的 Slice API 以及它在 Gatsby Cloud 上默认开启的构建优化能力如何在gatsby-node中用createSlice拆分公共 UI 组件、如何在页面中用Slice占位符复用它们以及为什么 Slice 组件变更在 Enterprise 站点上构建可以提速最多 90%。读完本文你将掌握 Slice 的完整使用姿势含参数、别名、查询与限制并理解其背后的源码级实现原理。一、为什么需要 SliceIncremental Builds 的延伸Gatsby 的 Incremental Builds增量构建已经显著缩短了构建时间——它只重建发生变化的页面。但页面的粒度仍然太粗在传统框架中当你调整头部Header内容时整个站点都必须重新构建哪怕只有头部这一小块变了。Gatsby Slice API 就是为了进一步解决这个问题而设计的。它的思路是把站点中公共的 UI 组件如 Header、Footer、导航栏抽出来构建成独立的 HTML 文件再由既有页面在需要时把它们拼接stitch回去。这样当某个公共组件变化时Gatsby 只需要构建这一个片段所有引用它的页面在需要时会自动拉取最新内容。Slice API 自gatsby5.0.0起提供支持。仓库中的 使用指南 对整体工作流有完整描述本文会在此基础上结合源码深入展开。二、Cloud OptimizationsGatsby Cloud 上的 Slice 构建优化这是 slices-optimization.md 的核心内容原文要点如下当站点使用 Slices 时Gatsby Cloud 可以进一步优化构建这些优化对所有 Enterprise 付费档次的站点默认启用无需额外配置通过精确掌握站点中哪些片段需要构建和托管Gatsby Cloud 可以让 Slice 变更时的构建时间最多提升 90%。换句话说优化不是黑魔法而是建立在信息之上的Gatsby Cloud 知道你的站点由哪些 Slice 组成、每个 Slice 挂在哪些页面上因此当某个 Slice 的组件或数据变化时它可以只构建和部署受影响的片段而不是整个站点。使用指南 中还给出了更细粒度的数据引入 Slices 后Gatsby Cloud 的构建时间整体可改善最多 20%而在 Gatsby Cloud Enterprise 上Slice 组件变更的构建可以最多快 90%。这两组数据是官方文档明确记录的结论用于说明 Slice 的收益随托管平台对站点结构认知的加深而放大。三、创建 SlicecreateSliceaction 与参数解析创建 Slice 的第一步是在gatsby-node的createPagesAPI 中调用createSliceactionexports.createPages async ({ actions }) { actions.createSlice({ id: navigation-bar, component: require.resolve(./src/components/navigation-bar.js), context: { jokeOfTheDay: Whats blue and not heavy? Light blue., } }) }createSlice的完整参数如下表参数类型说明id必填string该 Slice 的唯一标识别名Aliases机制依赖它见下文component必填string用作 Slice 组件的组件绝对路径contextobject以sliceContext的形式传给 Slice 组件的对象在源码层面createSlice实现在 packages/gatsby/src/redux/actions/restricted.ts 中且被登记为仅可用于createPages阶段的受限 action。它内部会做几件关键的事校验id必填缺失时直接report.panic错误码11334并提示Your sites gatsby-node.js must set the page path when creating a slice校验组件路径通过validateComponent检查组件路径是否缺失11333、是否为绝对路径11335、文件是否存在11336、文件是否为空11337、组件是否有默认导出11338并据此决定panic或panicOnBuild生成 chunk 名用generateComponentChunkName(payload.component, slice)为组件生成独立的componentChunkName——这正是Slice 单独构建、单独打包的起点记录变更信息对比旧状态计算componentModified与contextModified供增量构建判断是否需要重建该 Slice。四、在页面中使用Slice占位符Slice 创建好之后在页面/布局组件中导入gatsby提供的Slice组件来占位Slice aliasunique-name /Slice aliasunique-name additionalProphello world /Slice占位符的aliasprop 是必填的其余任意 prop 都会被透传给底层 Slice 组件。Prop类型说明alias必填string标识用哪个在gatsby-node中创建的 Slice 组件来替换此占位符详见下文 Aliases使用指南 中有一个经典场景站点有一个共享的DefaultLayout其中引用了Header组件import { Slice } from gatsby import { Footer } from ../components export const DefaultLayout ({ children, headerClassName }) { return ( div className{styles.defaultLayout} Slice aliasheader className{headerClassName} / {content} Footer / /div ) }这里把Header换成了Slice aliasheaderclassName等额外 prop 会继续传给实际的 Header Slice 组件。构建成功后gatsby build的输出中会列出站点构建出的 Slices 清单——看到它就说明 Slice 已经生效。五、sliceContext与 Slice 查询传递上下文和createPages可以为页面传context类似createSlice也可以为单个 Slice 组件传上下文exports.createPages async ({ actions }) { actions.createSlice({ id: header, context: { jokeOfTheDay: Whats blue and not heavy? Light blue., }, component: require.resolve(./src/components/header.js), }) }context中的数据会以sliceContext这个 key 传给 Slice 组件const Header ({ className, sliceContext }) { return ( div className{className} Link to/Home/Link Link to/jokes{sliceContext.jokeOfTheDay}/Link /div ) } export default HeaderSlice 查询Slice 组件也可以像页面一样导出graphql查询称为 slice queries从 Gatsby 数据层取数据结果通过dataprop 传入组件const Header ({ data }) { return ( div {data.allHeaderItems.nodes.map(headerItem ( Link to{headerItem.path}{headerItem.text}/Link ))} /div ) } export default Header export const query graphql query { allHeaderItems { nodes { path text } } } slice queries 还支持变量——变量来自createSlice传入的contextexport const query graphql query ($title: String) { myField(title: {eq: $title}) { id title } } 在构建流水线中这类查询由 packages/gatsby/src/services/run-slice-queries.ts 统一调度执行它会取出queryIds.sliceQueryIds通过processSliceQueries批量运行 slice queries并以 run slice queries 进度条的形式上报给 CLI保证 Slice 的查询与页面查询一样纳入构建管线。六、Aliases按页面定制 Slice 组件alias 是页面用来标识渲染哪个 Slice 组件的字符串。为什么引入 alias 而不是直接用createSlice的id因为alias 与页面是一一对应的映射关系。默认情况下createSlice里给的每个id都会自动生成一个同名 alias占位符写Slice aliasmy-image就会使用id为my-image的 Slice 组件。但如果需要按页面决定用哪个 Slice 组件可以在createPage中通过slices键传入 alias-to-id 映射exports.createPages async ({ actions }) { const animals [dog, cat, giraffe] for (const animal of animals) { // 为每种动物创建一个 slice如 my-image--dog actions.createSlice({ id: my-image--${animal}, component: require.resolve(./src/components/my-image-slice.js), context: { imagePath: ./images/${animal}.jpg, } }) actions.createPage({ path: /animals/${animal}, component: require.resolve(./src/templates/page.js), slices: { // 该页面上任何 Slice aliasmy-image 都使用 my-image--${animal} 这个 id my-image: my-image--${animal} } }) } }最常见的落地场景是多语言本地化为每种语言创建一个 Header Slice再为每个语言的每个页面指定对应语言的 Sliceconst SUPPORTED_LANGUAGES [en, jp, de] exports.createPages async ({ actions }) { // 为每种语言创建唯一 id 的 slice SUPPORTED_LANGUAGES.forEach(language { actions.createSlice({ id: header-${language}, context: { language }, component: require.resolve(./src/components/header.js), }) }) // 为每个页面节点 语言创建页面 pagesResult.data.edges.forEach(({ node }) { SUPPORTED_LANGUAGES.forEach(language { createPage({ path: node.path, component: require.resolve(./src/templates/page.js), context: { pagePath: node.path, language, }, slices: { // 该页面上的 Slice aliasheader 使用 header-${language} header: header-${language} } }) }) }) }下面的示意图展示了 alias 在页面、占位符与 Slice 组件之间的流转关系在存储层面alias 到组件 id 的映射由 packages/gatsby/src/redux/reducers/slices-by-template.ts 按页面模板组织管理而 packages/gatsby/src/redux/reducers/slices.ts 负责处理CREATE_SLICE事件将 Slice 的组件路径、上下文、chunk 名等写入 Redux 状态供后续构建阶段读取。七、使用限制与注意事项以下限制来自 Gatsby Slice API 参考文档使用前务必注意1. JSS 与 styled-components 暂不支持在 Slice 组件中使用 styled-components 或 JSS 目前不受支持可改用 emotion 或普通 CSS。2. 占位符必须位于src目录下Slice 占位符只能用在站点顶层src目录之下的文件中。以下位置可用SITE_ROOT/src/my-page.jsSITE_ROOT/src/components/my-component.js以下位置不可用SITE_ROOT/other-components/other-component.jsSITE_ROOT/other-library/other-component.js3. 不支持嵌套 SliceGatsby 不支持嵌套的 Slice 占位符。例如把高层的Layout做成 Slice 组件后这个Layout组件树中不能再出现其他Slice占位符。4. Context 不自动继承Slice 占位符不会继承父组件的 context。如果需要 context要么把 provider 加到wrapRootElement要么直接把值作为 prop 传给 Slice 组件需满足下方 Props 约束export function MyImage() { const location useLocation() return Slice aliasmy-image location{location} / }5. Props 约束alias必须可静态分析必须是内联字符串。以下写法都不行——来自父组件的 prop、来自函数调用的返回值// ⚠️ 不行不能使用父组件传入的 alias export function MyComponent({ sliceName }) { return Slice alias{sliceName} / }// ⚠️ 不行alias 不能来自函数调用 export function MyComponent() { const aliasName getAliasFromSomewhere() return Slice alias{aliasName} / }以下写法可行——局部常量字符串、模板字符串、直接内联// OK export function MyComponent() { const alias my-image return Slice alias{alias} / }// OK export function MyComponent() { const type image return Slice alias{my-${type}} / }// OK export function MyComponent() { return Slice aliasmy-image / }children无限制可以正常使用export function MyImage() { return ( Slice aliasmy-image pI am a caption, neat!/p /Slice ) }其余 prop 必须可序列化函数等不可序列化的值不能直接作为 prop 传递// ⚠️ 不行函数不可序列化 export function MyImage() { const fetchImage () { return /static/images/img.jpg } return Slice aliasmy-image fetchImage{fetchImage} / }// OK传给 Slice / 的 image 最终是字符串 export function MyImage() { const fetchImage () { return /static/images/img.jpg } return Slice aliasmy-image image{fetchImage()} / }八、源码级原理Slice 在 Gatsby 内部如何工作综合前文引用的源码Slice 的完整生命周期可以归纳为注册gatsby-node.js的createPages阶段调用createSlicerestricted.tsaction 校验id与组件路径、生成componentChunkName与context派发CREATE_SLICE落库slices.ts reducer 处理CREATE_SLICE把 Slice 及其componentModified/contextModified状态写入 Redux store页面通过createPage的slices键把 alias 映射到具体 slice id由 slices-by-template.ts 按模板组织查询构建时 run-slice-queries.ts 批量执行 slice queriesprocessSliceQueries查询结果连同sliceContext一起作为 props 提供给 Slice 组件构建与拼接Slice 组件因其独立的componentChunkName被单独构建为 HTML 片段页面在需要时引用这些片段完成拼接——这正是 Gatsby Cloud 能够只重建发生变化的 Slice、而非整站的基础。从源码结构看Slice 与页面走的是同一套 Redux 查询 构建流水线只是粒度更细因此可以与增量构建、Gatsby Cloud 的托管优化天然协同。九、构建输出与测试验证构建输出gatsby build成功后CLI 会打印本次构建出的Slices清单可用于确认 Slice 是否被正确识别与构建。单元测试在单元测试中需要 mockgatsby模块包括 Slice 占位符。配置后占位符会被替换为一个带有data-test-slice-alias自定义属性的div从而在测试中断言页面是否正确引用了指定 alias。十、相关文档与进一步阅读Enable Slices API Optimizations本文主题原文Gatsby Slice API 参考文档Using Slices 使用指南想进一步了解 Slice 与 TypeScript 的配合可参考using-slices相关章节官方文档路径为how-to/custom-configuration/typescript适用前提Slice API 需要gatsby5.0.0及以上版本Gatsby Cloud 的 Slice 构建优化对 Enterprise 档次的站点默认启用无需额外配置。如果站点尚未使用 Slice本文第三至第六节就是把它接入现有 Gatsby 站点的完整路线图。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表