webpack 服务端渲染配置

react的  服务端渲染有助于 seo优化 和 首屏速度快的优点 。

 

需要新建一个服务端的js,以供打包输出 react 字符串 到node端;

这里新建 server-entry.js

import React from "react";
import App from "./App.jsx";

// 这边输出了一个react 标签所以需要引入react

export default <App/>

然后  需要给他配一个能生产字符串的 webpack配置  在build目录下;

就是 webpack.config.server.js

然后复制一份之前的配置内容稍微  修改;

主要有几点 :1:在整个输出模块里新增target选项。

                        target:"node",

                       告诉webpack当前环境是node环境;

                      2,修改入口文件:

                      app:path.join(__dirname,"../client/server-entry.js")

                       3,修改打包后的文件名字

                       filename:"server-entry.js",

                      并且在 打包这一项 output对象这一项之前新增一个libraryTarget:'commonjs2',

                         表示打包采用的是 commonjs2的规范;

                    4,移除掉html-webpack-plugin

                     这里是服务端 所以不需要页面;

  然后在package.json里把脚本段改掉:

"scripts": {
    "build:client": "webpack --config build/webpack.config.js",
    "build:server": "webpack --config build/webpack.config.server.js",
    "clear": "rimraf dist",
    "build": "npm run clear && npm run build:client && npm run build:server"
  },

clear 命令是删除dist目录的 所以每次打包前 都删除dist目录;需要安装删除文件夹的node包    cnpm i -D rimraf

  build:client 和build:server 分别被执行一下; 生产服务端代码和客户端代码;

执行npm run build 就会得到三个文件,打开 server-entry.js就会看到 module.exports说明执行了 node环境的编码;

新建server.js  在client 文件夹下; node服务依赖于express 所以cnpm i -S express  

然后代码 如下

//引入express
const express = require("express");
//从react-dom的server文件夹下引入 关于服务端dom渲染的 方法;
const ReactSSR=require("react-dom/server");

//引入服务端关于 首屏的 前段打包压缩后的代码;由于是commonjs 所以 在default属性里了;
const serverENTRY=require("../dist/server-entry.js").default;




//调用express 生成app实例;
const app=express();

// * 页面上所有的请求统统都走 这个get方法
app.get("*",function (req,res) {

    // 把 首屏的代码 使用react的服务端的渲染方法 继续处理一下;
    const appString=ReactSSR.renderToString(serverENTRY);


    //页面渲染前端代码
   res.send(appString);

});

//监听 3444端口;
app.listen(3444,function () {
    console.log("server is running on 3444");
});

      然后再package.json里增加脚本, 

  "scripts": {
  "build:client": "webpack --config build/webpack.config.js",
  "build:server": "webpack --config build/webpack.config.server.js",
  "clear": "rimraf dist",
  "build": "npm run clear && npm run build:client && npm run build:server",
    "start":"node client/server.js"
}

然后就可以初步看到服务端渲染出一些内容了;

但是 在network里看不到任何关于其他引用的js, 这样肯定是不行的。 

正确的打开方式应该是 我们把原来的页面的html  拿到服务端来, 放置入 我们的打包好的内容,在输出到 页面这样 才是完整的页面输出;

所以在client下新建一个html 就叫tempalte 吧;

代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <div id="root"><app></app></div>

</body>
</html>

新增一个div   ,div里有个标签叫做app;占位用的  ;

在 app.js里把最后的render的路径改成 

ReactDom.render(<App/>,document.getElementById("root");

这样就会把<app></app> 标签替换掉;

然后在 webpack.config.js 里 的plugins 里新增一个配置

  //webpack的插件。 是一个数组,
    plugins:[new HTMLPlugin({
        // 意思就是模版的路径就是template.html,插入js用的
        template:path.join(__dirname,"../client/template.html")
    })]

然后在server.js里修改

// fs模块用于对系统文件及目录进行读写操作。
const fs =require("fs");
//引入path 
const path =require("path");

// 这边我们同步的方法来读取 html ,也就是要等待读取完成 才继续,制定utf-8
const template = fs.readFileSync(path.join(__dirname,"../dist/index.html"),"utf8");

在get方法里 使用 这个 html模版 ,替换掉占位符 重新插入到页面

// * 页面上所有的请求统统都走 这个get方法
app.get("*",function (req,res) {

    // 把 首屏的代码 使用react的服务端的渲染方法 继续处理一下;
    const appString=ReactSSR.renderToString(serverENTRY);

    //把原来div里的<app></app>替换成 appString
    template.replace("<app></app>",appString)

    //页面渲染前端代码
   res.send(template);

});

 

重新编译 就可以跑了

 

但是发现所有的请求都走*  这样就不对了 

所以应该是 

利用express的static静态资源文件的方法去处理 匹配到public文件目录的请求 ,也就是说都变成静态文件了。

//利用express的static静态资源文件的方法去处理 匹配到public文件目录的请求 ,也就是说都变成静态文件了。
app.use("/public",express.static(path.join(__dirname,"../dist")))

 

这样再重新编译就对了;

应用 服务端的代码,  React-dom.render()方法 就不能用了 ,对应的有一个专门用来给服务端注水的方法;

ReactDom.hydrate
ReactDom.hydrate(<App/>,document.getElementById("root"))

 

重新打包编译就完事

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值