react 服务端的改造

服务端实现 首屏渲染;

首先服务端要先支持es6;

cnpm i --save babel-cli

安装 babel包 先 ;

"scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom",
    "server": "NODE_ENV=test  nodemon  --exec babel-node server/server.js"
  },

server命令中把 原来的node 的nodemon  用--exec 替换成  babel-node  就可以了;

NODE_ENV=test 是说 node环境是测试;

 

现在node 环境就支持es6了 

 

然后服务端要支持jsx;

在package.json文件里把babel的值粘贴出来

   {
    "presets": [
      "react-app"
    ],
    "plugins": [
      [
        "import",
        {
          "libraryName": "antd-mobile",
          "style": "css"
        }
      ],
      "transform-decorators-legacy"
    ]
  }

在最外层新建 .babelrc文件 ,把上面的部分粘贴到到该文件 ,node中就支持jsx了;

 

如果你通过 <script> 标签加载React,这些高阶API可用于 ReactDOMServer 全局。

如果你使用ES6,你可以写成 

import ReactDOMServer from 'react-dom/server'

。如果你使用ES5,你可以写成 

var ReactDOMServer = require('react-dom/server')

 

这里我们

import ReactDOMServer from 'react-dom/server'

这个ReactDOMServer 里有2个方法;

一般都是用renderToString的;

这个方法可以把 jsx生成的的dom 编译成 node可以执行的 dom ;

function App() {
    return <div>hello world!!!!</div>
}

renderToString(<App></App>);

就变成了<div data-reactroot="">hello world!!!!</div> 这样 node就可以在首屏展示了;

我们把原来的 在首屏用的代码

//利用中间件拦截路由 改变最终执行路径;
app.use(function (req,res,next) {
    //定义路由 白名单 ,把静态资源放置进去;
    //如果url路径是/user或者/static 说明是 用户的请求 或者静态的资源,这样就还是执行原来的下一个方法
    if(req.url.startsWith("/user/")||req.url.startsWith("/static/")){
    return next();
    }

    const html=ReactDOMServer.renderToString(<App></App>)
   
    return res.send(html);

     //否则就去加载 静态资源路径了;
  // return res.sendFile(path.resolve("build/index.html"));
});

把原来首屏加载文件的

return res.sendFile(path.resolve("build/index.html"));

改为 

res.send(html);

这样就完成了首屏显示;

下面来改写之前的项目;

把原来的index的公用部分重新抽离出来一个app.js

import  React from "react";
import {Route,Switch} from "react-router-dom"
import Login from "./container/login/login"
import Register from "./container/register/register"
import AuthRoute from "./container/authRoute/AuthRoute"
import Bossinfo from "./container/bossinfo/bossinfo"
import Niureninfo from "./container/niureninfo/niureninfo"
import DashBoard from "./container/dashboard/dashboard"
import Chat from "./container/chat/chat"
class App extends React.Component{
    render(){
        return(
            <div>
                <AuthRoute/>
                <Switch>
                    <Route path="/niureninfo" component={Niureninfo}/>
                    <Route path="/bossinfo" component={Bossinfo} />
                    <Route path="/login" component={Login}/>
                    <Route path="/register" component={Register} />
                    <Route path="/chat/:user" component={Chat} />
                    <Route component={DashBoard}/>
                </Switch>
            </div>
        )
    }
}

export  default  App;

然后 index 就成了一个 比较独立的存在 

import  React from "react"
import  ReactDom from "react-dom"
import  {createStore,applyMiddleware,compose} from "redux";
import  thunk from "redux-thunk"
import {Provider} from "react-redux"
import {BrowserRouter} from "react-router-dom"
import reducers from  "./reducers"
import App from "./app"
import "./config"
import "./app.css"

const store=createStore(reducers,compose(applyMiddleware(thunk),
    window.devToolsExtension?window.devToolsExtension():()=>{}
));

    ReactDom.render(
        <Provider store={store}>
            <BrowserRouter>
              <App/>
            </BrowserRouter>
           </Provider>
        ,document.getElementById("root"))


在server.js 去  把provider相关的全部 写到那个 中间件 里输出出来;  上面该定义的定义,该引入的引入;

import  {createStore,applyMiddleware,compose} from "redux";
import  thunk from "redux-thunk"
import {Provider} from "react-redux"
import {StaticRouter} from "react-router-dom"
import reducers from  "../src/reducers"
import App from "../src/app"
import "../src/config"
import "../src/app.css"
//利用中间件拦截路由 改变最终执行路径;
app.use(function (req,res,next) {
    //定义路由 白名单 ,把静态资源放置进去;
    //如果url路径是/user或者/static 说明是 用户的请求 或者静态的资源,这样就还是执行原来的下一个方法
    if(req.url.startsWith("/user/")||req.url.startsWith("/static/")){
    return next();
    }

    //如果路由有跳转可以告诉我们路由有没有跳转;
    const context={};
    const store=createStore(reducers,compose(applyMiddleware(thunk) ));
    const markUp=ReactDOMServer.renderToString(
        (
            <Provider store={store}>
                <StaticRouter
                context={context}
                location={req.url}
                >
                    <App/>
                </StaticRouter>
            </Provider>

        )
    );
  //  const html=ReactDOMServer.renderToString(<App></App>);
    return res.send(markUp);
     //否则就去加载 静态资源路径了;
  // return res.sendFile(path.resolve("build/index.html"));
});

其中要注意 的是 BrowserRouter 要改为服务端的 StaticRouter;并且要加入两参数 location  ,context;

              <StaticRouter
                context={context}
                location={req.url}
                >
                    <App/>
                </StaticRouter>

context是 用来 告诉我们路由有没有跳转的;

这个时候会报错 ,因为css和图片 在后端没有办法加载, 需要挂载;

先安装 工具包

cnpm i --save css-modules-require-hook

去这地址http://npm.taobao.org/package/css-modules-require-hook

找到  Using with babel-node / ES6 Imports  这行

下面的代码就是我们要用的:

在server.js引入

// server.js
import csshook from 'css-modules-require-hook/preset' // import hook before routes

这句代码要放到 引入app之前 ,    

在最外层编写配置文件 cmrh.conf.js

// cmrh.conf.js
module.exports = {
  // Same scope name as in webpack build
  generateScopedName: '[name]__[local]___[hash:base64:5]',
}

依然会报引入图片的错误;继续安装包;

cnpm i --save asset-require-hook

然后装包成功以后;

打开地址https://github.com/aribouius/asset-require-hook

然后在server.js引入 

//asset-hook.js
import assethook from "asset-require-hook";

然后在下面执行一下(放到引入app之前);

assethook({
    extensions: ['jpg']
});

 

然后还需要真个页面的骨架 ,

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
  <meta name="theme-color" content="#000000">
 
  <title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

然后 把 原来写的markUp 放到 root的div里;

  const page = `<!DOCTYPE html>
    <html lang="en">
     <head>
        <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1, 
               maximum-scale=1, minimum-scale=1, user-scalable=no" />
             <meta name="theme-color" content="#000000">
                <link rel="stylesheet" href="">
                  
                <title>51job</title>
        </head>
       <body>
         <div id="root">${markUp}</div>
        </body>
    </html>`;

引入 原来生成的那个目录;build文件夹下asset-manifest.json文件;

import assetmanifest from "../build/asset-manifest"

引入该文件  css,js文件 ;

  <link rel="stylesheet" href=${assetmanifest["main.css"]}>
<script src=${assetmanifest["main.js"]}></script>

 

const page = `<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
            <meta name="theme-color" content="#000000">
                <link rel="stylesheet" href=${assetmanifest["main.css"]}>
                  
                        <title>51job</title>
    </head>
    <body>
    <div id="root">${markUp}</div>
    </body>
    <script src=${assetmanifest["main.js"]}></script>
    </html>`;

 

至此 ,大功告成。

 

 

 

<think>嗯,用户让我比较React和Vue的区别以及各自的优势。首先,我需要回顾这两个框架的基本信息。React是Facebook开发的,而Vue是尤雨溪创建的。它们的核心思想可能不同,React更注重灵活性和函数式编程,而Vue可能更倾向于易用性和渐进式框架。 接下来,我得考虑它们的语法差异。React使用JSX,把HTML和JavaScript结合在一起,而Vue则使用模板语法,可能更接近传统的HTML。这可能影响到开发者的学习曲线和项目的结构。 然后是状态管理。React需要依赖像Redux或Context API这样的第三方库,而Vue有内置的Vuex,现在可能升级到Pinia了。这方面Vue可能更一体化,React则更灵活,可以选择不同的解决方案。 响应式原理方面,Vue使用的是数据劫持,通过getter和setter自动追踪变化,而React则依赖于状态更新后的显式重新渲染,比如setState。这可能让Vue在简单场景下更直观,而React在复杂应用中有更好的控制。 组件化方面两者都支持,但Vue的单文件组件(.vue文件)把模板、脚本和样式放在一起,结构清晰。React的组件则是JavaScript函数或类,可能更灵活,但需要开发者自己组织代码。 生态系统和社区也是重要的点。React有更庞大的社区和更多的第三方库,适合大型项目,而Vue的中文文档和更温和的学习曲线可能对新手友好,适合快速开发。 性能方面,两者都采用虚拟DOM,但Vue3的优化可能让它在某些情况下更快,比如编译时的优化。React的Fiber架构改进了异步渲染,可能处理大型应用更高效。 适用场景的话,React适合需要高度定制和复杂状态管理的项目,而Vue适合中小型项目或需要快速上手的团队。同时,Vue的渐进式特性让它可以逐步集成到现有项目中,这也是一个优势。 可能用户是前端开发者,想选型新项目,或者面试需要了解两者的区别。需要确保回答全面,同时突出各自的优点,帮助用户根据项目需求做决策。还要注意用中文,结构清晰,分点说明,符合用户的要求。</think>React 和 Vue 是当前最主流的前端框架,以下是它们的核心差异与优势对比: --- ### 一、核心架构差异 1. **设计理念** - **React**:专注 UI 层,主张函数式编程(`组件 = f(state)`) - **Vue**:渐进式框架,提供开箱即用的完整解决方案(模板系统 + 状态管理 + 路由等) 2. **语法形式** - **React**:使用 JSX(JavaScript + HTML 混合写法) ```jsx const Button = ({ onClick }) => ( <button onClick={onClick}>Click me</button> ) ``` - **Vue**:基于 HTML 的模板语法 ```vue <template> <button @click="onClick">Click me</button> </template> ``` --- ### 二、核心优势对比 | 特性 | React | Vue | |---------------------|--------------------------------|------------------------------| | **学习曲线** | 需要掌握 JSX、函数式编程思想 | 模板语法更接近传统 HTML | | **响应式原理** | 手动控制重新渲染 (`setState`) | 自动依赖追踪 (数据劫持) | | **状态管理** | 依赖第三方库 (Redux/Zustand) | 内置 Vuex/Pinia | | **灵活性** | 高度灵活,需自行选型生态 | 官方提供完整工具链 | | **跨平台能力** | 成熟方案 (React Native) | 新兴方案 (Uni-app/NativeScript) | --- ### 三、典型使用场景 1. **React 更适用场景** - 大型复杂应用(如 Facebook、Instagram) - 需要高度定制化技术栈 - 团队具备较强 JavaScript 基础 2. **Vue 更适用场景** - 快速开发中小型项目 - 需要更低的学习成本(尤其对 HTML/CSS 开发者友好) - 渐进式集成到现有项目(如 jQuery 项目改造) --- ### 四、性能对比(Vue3 vs React 18) | 指标 | Vue3 (Proxy) | React 18 (Fiber) | |-------------------|--------------------------------|-------------------------------| | **编译优化** | 编译时标记动态节点 | 运行时优化 | | **包体积** | 核心库约 33KB (gzip) | 核心库约 42KB (gzip) | | **SSR 性能** | 更轻量的服务端渲染方案 | 需要配合 Next.js 等框架 | --- ### 五、开发者选择建议 1. **选择 React 的理由** - 生态丰富(测试工具、UI 库等更成熟) - 函数式编程更符合现代开发趋势 - 大型团队协作的工程化支持更好 2. **选择 Vue 的理由** - 中文文档友好,国内生态完善 - 组合式 API 简化复杂逻辑复用 - 更"温和"的升级策略(如 Vue2 → Vue3) --- ### 六、代码模式对比(计数器示例) ```jsx // React 实现 function Counter() { const [count, setCount] = useState(0); return ( <div> <p>{count}</p> <button onClick={() => setCount(c => c + 1)}>+1</button> </div> ); } ``` ```vue <!-- Vue 实现 --> <template> <div> <p>{{ count }}</p> <button @click="count++">+1</button> </div> </template> <script setup> import { ref } from 'vue'; const count = ref(0); </script> ``` --- ### 七、发展趋势 - **React**:持续强化并发渲染能力(Server Components、Suspense) - **Vue**:深耕开发者体验(Vite 工具链、TypeScript 深度集成) 两者都在向更高效的编译时优化方向发展(React Forget 编译器、Vue 宏语法)。选择时更应关注团队技术栈适配性而非绝对优劣。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值