ARTICLE DETAIL

资讯详情

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

Next.js 集成 Plasmic:基于 Static Generation 与 Preview Mode 实现无代码视觉建站

Next.js 集成 Plasmic:基于 Static Generation 与 Preview Mode 实现无代码视觉建站 Next.js 集成 Plasmic基于 Static Generation 与 Preview Mode 实现无代码视觉建站【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js本篇技术文章基于 Next.js 官方仓库中的示例 examples/cms-plasmic讲解如何用 Plasmic 这一可视化页面构建器驱动 Next.js 静态生成Static Generation站点从获取 Project ID 与 API Token、配置环境变量到理解 catch-all 页面的getStaticPaths/getStaticProps实现、ISR 增量再生成再到利用 Preview Mode 在开发环境中实时预览 Plasmic Studio 中的未发布修改。读完本文你可以完整复制、运行并部署这套「设计即代码」的页面生成工作流。示例能力与目录结构该示例展示的是 Next.js 静态生成能力与 Plasmic 视觉构建器的组合页面不再由开发者手写 JSX而是由非开发者在 Plasmic Studio 中拖拽设计后发布Next.js 在构建/请求时拉取页面元数据并静态渲染。官方 README 概括了该示例提供的两项核心能力从可视化设计直接生成静态页面Statically generated pages from your visual designs开发服务器借助 Next.js 的 Preview Mode实时监听 Plasmic Studio 中的变更。示例的完整文件布局如下理解这张地图是后续源码剖析的基础examples/cms-plasmic/ ├── pages/ │ ├── [[...catchall]].tsx # 核心Plasmic 页面的 catch-all 渲染入口 │ ├── _app.js # 全局入口仅引入全局样式 │ └── api/ │ ├── preview.ts # 开启 Draft Mode 的预览开关接口 │ └── exit-preview.ts # 退出 Draft Mode 的接口 ├── plasmic-init.ts # Plasmic 加载器初始化双 Loader 设计 ├── styles/globals.css # 全局样式 ├── public/favicon.ico # 站点图标 ├── next.config.js # Next.js 配置仅开启 reactStrictMode ├── package.json ├── tsconfig.json ├── .env.local.example # 环境变量模板 └── README.md依赖关系上package.json 声明了唯一的 Plasmic 侧依赖plasmicapp/loader-nextjs版本1.0.363配合next: latest与 React 18.3。next.config.js 保持最简配置仅设置reactStrictMode: true说明该方案不需要额外的 Webpack/SWC 定制。准备工作用 create-next-app 拉取示例官方提供 npm、Yarn、pnpm 三种脚手架方式执行对应命令即可把示例拷贝为本地项目cms-plasmic-appnpx create-next-app --example cms-plasmic cms-plasmic-appyarn create next-app --example cms-plasmic cms-plasmic-apppnpm create next-app --example cms-plasmic cms-plasmic-appscaffold之后项目的启动脚本定义在 package.json 中dev对应next devbuild对应next buildstart对应next start。配置 Plasmic 项目Project ID 与 API Token在使用代码之前需要先完成 Plasmic 侧的两步准备对应 README 的 Step 1、Step 2注册账号并创建项目在 Plasmic Studio 中注册账号随后创建一个新 Project收集凭据Project ID打开项目后直接体现在 URL 中形如https://studio.plasmic.app/projects/PROJECTID其中PROJECTID即为所需值API Token点击 Studio 顶栏的 Code 按钮即可获取。这两个值会分别写入后文的环境变量并被 plasmic-init.ts 在运行时读取。环境变量配置示例目录提供了模板文件 .env.local.example其内容为NEXT_PUBLIC_PLASMIC_PROJECT_ID NEXT_PUBLIC_PLASMIC_PROJECT_API_TOKEN PLASMIC_PREVIEW_SECRET按 README 指引先复制模板cp .env.local.example .env.local.env.local会被 Git 忽略避免凭据入库。三个变量的含义与取值如下变量说明取值来源NEXT_PUBLIC_PLASMIC_PROJECT_IDPlasmic 项目 ID因带NEXT_PUBLIC_前缀会暴露给浏览器端上一步从 Studio URL 中读取的PROJECTIDNEXT_PUBLIC_PLASMIC_PROJECT_API_TOKEN拉取页面元数据所需的 API TokenStudio 顶栏 Code 按钮中获取的 TokenPLASMIC_PREVIEW_SECRETPreview Mode 接口的鉴权密钥仅服务端可见任意随机字符串避免空格如MY_SECRET启动开发服务器依赖安装与启动命令README Step 4npm install npm run dev # 或 yarn install yarn dev启动后站点运行在http://localhost:3000。pages/_app.js 是最标准的 Pages Router 入口只做两件事引入 styles/globals.css 并把pageProps透传给路由组件——这也解释了为什么所有 Plasmic 页面都能拿到getStaticProps注入的plasmicData与queryCache。源码剖析一plasmic-init.ts 的双 Loader 设计整个示例的 Plasmic 集成逻辑集中在 plasmic-init.ts全文仅 26 行import { initPlasmicLoader } from plasmicapp/loader-nextjs; const PLASMIC_PROJECT_ID process.env[NEXT_PUBLIC_PLASMIC_PROJECT_ID]; const PLASMIC_PROJECT_API_TOKEN process.env[NEXT_PUBLIC_PLASMIC_PROJECT_API_TOKEN]; const PLASMIC_CONFIG { projects: [ { id: PLASMIC_PROJECT_ID, token: PLASMIC_PROJECT_API_TOKEN, }, ], }; export const PLASMIC initPlasmicLoader({ ...PLASMIC_CONFIG, preview: false, }); export const PREVIEW_PLASMIC initPlasmicLoader({ ...PLASMIC_CONFIG, // Fetches the latest revisions, whether or not they were unpublished! // Disable for production to ensure you render only published changes. preview: true, });这里有值得注意的设计决策用同一份项目配置创建了两个加载器仅以preview开关区分。PLASMICpreview: false只构建「已发布published」的 Plasmic 项目版本用于正式渲染。这也是 README Step 5 所说「默认代码只构建已发布的 Plasmic 项目」的源码出处PREVIEW_PLASMICpreview: true源码注释明确写道它「会拉取最新修订无论是否已发布」。它只在 Preview Mode 下启用让开发者/编辑在 Studio 里的每次未发布修改都能被开发服务器实时反映。从源码结构看这种「双 Loader」模式是 Plasmic 官方推荐的隔离手段生产渲染路径与草稿预览路径使用不同的数据源避免未发布内容泄漏到线上。源码剖析二[[...catchall]].tsx 与静态生成 ISRpages/[[...catchall]].tsx 是示例的核心页面以可选 catch-all 路由承接 Plasmic 中的所有页面路径。它包含三段逻辑getStaticPaths从 Plasmic 拉取全部页面路径export const getStaticPaths: GetStaticPaths async () { const pages await PLASMIC.fetchPages(); return { paths: pages.map((page) ({ params: { catchall: page.path.substring(1).split(/) }, })), fallback: blocking, }; };PLASMIC.fetchPages()返回在 Studio 中已创建的全部页面每一页的page.path如/about去掉前导斜杠后按/切分成数组映射为catchall参数。fallback: blocking意味着遇到构建时尚未枚举到的路径时页面会先展示 loading 并触发按需生成——这让「在 Studio 中新建页面」无需重新构建即可被访问。getStaticProps预取组件数据并启用 ISRexport const getStaticProps: GetStaticProps async (context) { const { catchall } context.params ?? {}; // Convert the catchall param into a path string const plasmicPath typeof catchall string ? catchall : Array.isArray(catchall) ? /${catchall.join(/)} : /; const plasmicData await PLASMIC.maybeFetchComponentData(plasmicPath); if (!plasmicData) { // This is some non-Plasmic catch-all page return { props: {} }; } // This is a path that Plasmic knows about. // Cache the necessary data fetched for the page. const queryCache await extractPlasmicQueryData( PlasmicRootProvider loader{PLASMIC} prefetchedData{plasmicData} PlasmicComponent component{plasmicData.entryCompMetas[0].displayName} / /PlasmicRootProvider, ); return { props: { plasmicData, queryCache, preview: context.preview ?? null }, // Using incremental static regeneration, will invalidate this page // after 300s (no deploy webhooks needed) revalidate: 300, }; };这段代码体现了 Plasmic 集成的完整数据管线路径还原把catchall参数字符串或数组归一化为 Plasmic 侧的路径字符串根路径为/组件数据预取PLASMIC.maybeFetchComponentData(plasmicPath)拉取渲染该页面所需的ComponentRenderData若该路径并非 Plasmic 页面返回空则直接返回空 props 交给组件侧渲染 404Query 缓存抽取extractPlasmicQueryData(...)在服务器端对PlasmicRootProvider包裹的组件树做「试渲染」把页面内各类数据源如内容查询的响应收集进queryCache从而避免客户端二次请求这是静态性能的关键Preview 标记传递context.preview被原样注入 props供组件判断是否走预览加载器ISRrevalidate: 300声明增量静态再生成——页面在 5 分钟后自动失效重建无需部署 Webhook 即可让 Plasmic 中发布的更新最终同步到静态站点。组件渲染按 preview 切换加载器export default function CatchallPage(props: { plasmicData?: ComponentRenderData; queryCache?: Recordstring, any; preview?: boolean; }) { const { plasmicData, queryCache, preview } props; if (!plasmicData || plasmicData.entryCompMetas.length 0) { return Error statusCode{404} /; } const pageMeta plasmicData.entryCompMetas[0]; return ( PlasmicRootProvider loader{preview ? PREVIEW_PLASMIC : PLASMIC} prefetchedData{preview ? undefined : plasmicData} prefetchedQueryData{preview ? undefined : queryCache} PlasmicComponent component{pageMeta.displayName} / /PlasmicRootProvider ); }渲染细节有两处值得品味404 兜底plasmicData缺失或entryCompMetas为空时渲染 Next.js 内建Error statusCode{404} /覆盖「非 Plasmic 路径」与「Plasmic 已删页」两类情况预览时丢弃预取数据preview为真时改用PREVIEW_PLASMIC加载器并刻意将prefetchedData/prefetchedQueryData置为undefined——因为草稿内容在 Studio 中随时变化构建期预取的数据已不可信预览态必须走加载器实时拉取。而pageMeta.displayName即entryCompMetas[0].displayName指明的是 Plasmic 中该页面对应的组件名PlasmicComponent据此完成最终渲染。Preview Mode在开发环境实时预览 Studio 修改README Step 5 说明默认只构建已发布项目若要看到 Studio 中的实时修改需要进入 Preview Mode。开启预览——浏览器访问http://localhost:3000/api/preview?secretPLASMIC_PREVIEW_SECRETslugPATH务必把PLASMIC_PREVIEW_SECRET替换为 Step 3 中设置的密钥slug为要预览的 Plasmic 页面路径例如http://localhost:3000/api/preview?secret123456slug/退出预览——随时访问http://localhost:3000/api/exit-preview进入预览后Studio 中的每次编辑都会在开发服务器页面上实时呈现这正是PREVIEW_PLASMICpreview: true存在的意义。从源码看pages/api/preview.ts 做了一道完整的安全校验链export default async function preview(req, res) { // Check the secret and next parameters if ( req.query.secret ! process.env.PLASMIC_PREVIEW_SECRET || !req.query.slug ) { return res.status(401).json({ message: Invalid token }); } // Check if the page with the given slug exists const pages await PREVIEW_PLASMIC.fetchPages(); const pageMeta pages.find((p) p.path req.query.slug); if (!pageMeta) { return res.status(401).json({ message: Invalid slug }); } // Enable Draft Mode by setting the cookie res.setDraftMode({ enable: true }); // We dont redirect to req.query.slug as that might lead to // open redirect vulnerabilities res.redirect(pageMeta.path); }三个安全要点secret 不匹配或缺 slug 直接 401slug 必须是 Plasmic 中真实存在的页面路径否则同样拒绝最终重定向的目标取自服务端校验后的pageMeta.path而非用户传入的原始参数从而规避开放重定向open redirect漏洞。pages/api/exit-preview.ts 则通过res.setDraftMode({ enable: false })删除 Draft Mode cookie再以 307 重定向回首页。部署到 VercelREADME Step 6 给出云端部署路径把本地项目推送到 Git 平台后导入 Vercel 即可。关键注意点原文加粗强调Important在 Vercel 导入项目时务必进入Environment Variables面板把三个环境变量设置为与.env.local一致的值。漏配任一变量都会导致运行时PLASMIC_PROJECT_ID/PLASMIC_PROJECT_API_TOKEN为空、页面无法渲染PLASMIC_PREVIEW_SECRET缺失则 Preview Mode 接口会持续返回 401。后续扩展如 README「Next steps」所述引入 Plasmic 的价值在于让团队中的非开发者也能发布页面与内容——设计师在 Studio 中完成视觉工作Next.js 负责高性能的静态渲染与增量再生成两者通过plasmicapp/loader-nextjs的fetchPages/maybeFetchComponentData/extractPlasmicQueryData三个 API 解耦协作。若需进一步了解 Plasmic 的组件体系、数据源与协作工作流可参考官方文档与开源仓库Plasmic 官网、docs.plasmic.app 与 Plasmic GitHub 仓库。相关示例仓库中与本示例同属 CMS 集成类别的官方示例位于 examples 目录包括AgilityCMSBuilder.ioButterCMSContentfulCosmicDatoCMSDotCMSDrupalEnterspeedGhostGraphCMSKontent.aiMakeSwiftPayloadPlasmicPreprPrismicSanitySitecore XM CloudSitefinityStoryblokTakeShapeTinaUmbracoUmbraco heartcoreWebinyWordPressBlog Starter【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表