当前位置: 首页 > news >正文

南昌网站搭建公司 赣ICP深圳广告公司排名

南昌网站搭建公司 赣ICP,深圳广告公司排名,成都手机号码网站建设,企业网站管理系统添加教程一、背景 目前主流的前端架构分为SSR、CSR、SSG#xff0c;比较适合首屏直出的方案除了CSR都还不错#xff0c;因为服务端会直接返回路由对应的html css#xff0c;浏览器直接解析DOM即可#xff0c;而水合的作用是什么#xff1f;服务端首次返回的是静态页面#xff0…一、背景 目前主流的前端架构分为SSR、CSR、SSG比较适合首屏直出的方案除了CSR都还不错因为服务端会直接返回路由对应的html css浏览器直接解析DOM即可而水合的作用是什么服务端首次返回的是静态页面页面需要”动“起来的话则需要水合即将页面所需的JS引入并加载、给DOM绑定交互等等核心的API即ReactDOM.hydrateRoot。 二、同构渲染 这样服务端渲染一次、客户端渲染一次的流程也称为同构渲染一般情况是通过Nodejs实现文件服务基于组件文件通过React Server API——renderToString就像这样 import { renderToString } from react-dom/server; import App from ./App;console.log(renderToString(App/));而在客户端接收到服务端渲染所生成的html string后基于客户端水合API——react DOM API——hydrateRoot进行组件与静态标签的关联就像这样 import React from react; import { hydrateRoot } from react-dom/client; import ./index.css; import App from ./App;hydrateRoot(document.getElementById(root), App/);三、手写一个SSR 基于同构渲染的秘密我们解开了那手写一个基础的SSR服务其实很简单我们可以把整个加载链路拆解成三步 起一个本地express服务用于按路由返回html前端构建时约定式路由/pages解析每个路由下的根组件生成html模板webpack构建工程代码产出bundle.js前端项目中引入bundle.js进行同构渲染水合逻辑 整体的项目工程如下 ├── .next // 生成文件服务html、构建结果 ├── src │ ├── pages // 页面 │ │ ├── a.jsx // 页面A │ │ ├── b.jsx // 页面B │ │ ├── c.jsx // 页面C │ ├── client.js // 水合 ├── generateHtml.js // 路由转换html能力 ├── server.js // 文件服务 ├── teamplate.html // html基础模板 ├── webpack.config.js └── package.json3.1、文件服务搭建 我们起一个简单的工程项目并安装基础依赖。 mkdir ssr-demo cd ssr-demo npm init -y npm i express react react-dom webpack webpack-cli fs-extraexpress服务代码如下 const express require(express); const path require(path);// 定义根目录 const rootDir path.resolve(__dirname, ./); const outputDir path.join(rootDir, .next);const app express(); const PORT process.env.PORT || 3000;// 提供 .next 目录的静态文件服务 app.use(express.static(outputDir));// 启动服务器 app.listen(PORT, () {console.log(Server is running on http://localhost:${PORT}); }); 代码中启用了静态文件服务在路由解析服务实现后每次项目构建阶段都会在.nest路由生成所有页面的html用于在服务端直接返回。 3.2、路由解析服务 接下来我们实现服务端核心部分将所有路由的组件解析成html模板在此之前需要有一个基础的html模板用于动态插入组件部分的标签html模板如下 !DOCTYPE html html langenheadmeta charsetUTF-8 /titleMy App/title/headbody data-component{{componentName}}{{content}}script src/client.bundle.js defer/script/body /html其中content是实际渲染的组件标签、componentName用于在后续水合阶段定位组件、script用于执行水合逻辑。 遍历生成所有html文件的代码如下 // src/generate.js require(babel/register)({presets: [babel/preset-env, babel/preset-react], });const fs require(fs-extra); // 使用 fs-extra 方便处理文件 const path require(path); const React require(react); const ReactDOMServer require(react-dom/server);// 定义根目录 const rootDir path.resolve(__dirname, ./); const pagesDir path.join(rootDir, src/pages); const outputDir path.join(rootDir, .next);// 生成 HTML 文件 const generateHtmlFiles () {return new Promise((resolve, reject) {fs.readdir(pagesDir, (err, files) {if (err) {reject(Error reading pages directory);return;}const promises files.map((file) {const filePath path.join(pagesDir, file);const fileExt path.extname(file);// 只处理以 .jsx 结尾的文件if (fileExt .jsx) {const pageName path.basename(file, fileExt);const PageComponent require(filePath).default; // 导入组件const renderedContent ReactDOMServer.renderToString(React.createElement(PageComponent));const templatePath path.resolve(__dirname, template.html); // Load HTML templatereturn new Promise((resolve, reject) {fs.readFile(templatePath, utf8, (err, template) {if (err) {console.error(Error loading template:, err);reject(err);return;}const html template.replace({{content}}, renderedContent).replaceAll({{componentName}}, pageName); // 注入组件名称// 构造输出路径放在以页面名字为名的文件夹中const outputDirForPage path.join(outputDir, pageName);const outputFilePath path.join(outputDirForPage, index.html);fs.ensureDirSync(outputDirForPage); // 确保页面目录存在fs.outputFileSync(outputFilePath, html, utf8);console.log(Generated HTML for ${pageName}: ${outputFilePath});resolve();});});}return Promise.resolve(); // 对于不是 .jsx 文件的情况});Promise.all(promises).then(() resolve(HTML generation completed!)).catch(reject); // 处理生成过程中的异常});}); };// 直接调用生成函数并输出结果 generateHtmlFiles().then((message) {console.log(message);process.exit(0); // 结束进程}).catch((err) {console.error(err);process.exit(1); // 发生错误结束进程}); 3.3、webpack打包前端工程 这里比较好理解整个前端客户端代码也需要打包包括水合的代码我们基于webpack构建初始化一个基础的打包配置 const path require(path);module.exports {entry: path.resolve(__dirname, src, client.js),output: {path: path.resolve(__dirname, .next), // 输出到 .next 目录filename: client.bundle.js, // 根据入口名称生成文件名publicPath: /, // 公开路径},module: {rules: [{test: /\.(js|jsx)$/,exclude: /node_modules/,use: {loader: babel-loader,options: {presets: [babel/preset-env, babel/preset-react],},},},],},resolve: {extensions: [.js, .jsx],},mode: production, // 可以根据需要设置为 development };配置完webpack之后我们前三步的流程可以串起来了这个效果和webpack dev server比较类似我们基于流程顺序配置对应的package.json scripts scripts: {build: webpack --config webpack.config.js,generate: node generateHtml.js,server: node server.js,start: npm run build npm run generate npm run server},build负责构建前端工程generate负责生成所有页面的htmlserver负责创建最终的文件服务 3.4、渲染的终点——水合 这段代码运行时服务端已经返回html文件此时是同构渲染的终点通过hydrateRoot API将服务端的标签在浏览器水合让页面组件动起来即可。 实现代码 // // src/client.js import React from react; import ReactDOM from react-dom/client;console.log(React); const hydrateComponent (componentName) {// 动态 import 组件import(./pages/${componentName}.jsx).then(({ default: Component }) {const domContainer document.getElementById(componentName);if (domContainer) {ReactDOM.hydrateRoot(Component /, domContainer);} else {console.error(No container found for component ${componentName});}}).catch((error) {console.error(Error loading component:, error);}); };// 从 HTML 中提取组件名称然后进行水合 document.addEventListener(DOMContentLoaded, () {const componentName document.body.getAttribute(data-component);hydrateComponent(componentName); }); 至此整个demo就完成了。 大致的效果如下 结尾 本文希望对于原本不是很了解SSR、SSG方案的同学可以快速的理解与传统单页应用的区别并且可以基于这个demo了解到服务端渲染、webpack dev server的工作原理。 对于实现同构渲染的方案有建议的同学欢迎评论探讨。
http://www.w-s-a.com/news/3547/

相关文章:

  • 专门做二手书网站或appwordpress首页显示特定分类文章
  • 无锡网站设计厂家一建十个专业含金量排名
  • 网站刷链接怎么做成都高度网站技术建设公司
  • flash网站模板怎么用xml网站地图生成
  • 英文网站优化群晖wordpress中文
  • saas建站平台源码济南品牌网站建设公司
  • 网站建设一般是用哪个软件网站百度
  • 企业建站的作用是什么南宁公司网站开发
  • 厦门网站建设及维护门户网站开发视频教学
  • 可以做兼职的网站有哪些自动点击器永久免费版
  • 建购物网站怎么建呀网站怎么做中英文交互
  • 网站建设费用计入无形资产做网站用的主机
  • 佛山企业网站建设平台沈阳网站建设培训班
  • 河南企业网站优化外包网站怎么做来流量
  • 网站建设的参考文献网站设计网页的优缺点
  • WordPress多站點支付插件内江市网站建设培训
  • 做做网站已更新动漫制作专业需要学什么
  • dfv印花图案设计网站网站建设应该应聘什么岗位
  • 网站后台管理系统模板下载专业网站推广的公司哪家好
  • 克拉玛依市建设局网站网页设计板式重构
  • 网站新闻专题怎么做湖南营销型网站建设 要上磐石网络
  • 阿里云发布网站成都轨迹公布
  • php网站源码架构谷歌站群系统
  • 潮州网站seowordpress 调用置顶文章
  • 做带会员后台的网站用什么软件旅游网站建设资金请示
  • 商品网站怎么做wordpress 表情拉长
  • 商城网站设计费用网络公司怎样推广网站
  • 视频公司的网站设计工图网
  • 免费快速网站十八个免费的舆情网站