从0搭建前端项目架构-第二篇-服务端渲染配置

492 阅读2分钟

上一篇文章总结了webpack基础配置,这篇文章开始总结服务端渲染配置。

服务端渲染配置

1.在client目录里新建服务端入口文件server-entry.js

    cd cliennt
    touch server-entry.js

2.在server-entry.js里面写的是导出前端代码

    import React from 'react';
    import App from './App.jsx';
    
    export default <App />

3.因为打包时不能打包服务端文件,需要新建webpack.config.server.js来配置

  • target:node 代表运行在node环境中。
  • libraryTarget: 'commonjs2' 代表遵循common.js规范
    const path = require('path');
    module.exports = {
        target:'node',
        entry: {
            app: path.join(__dirname,'../client/server-entry.js')
        },
        output: {
            filename: 'server-entry.js',
            path: path.join(__dirname,'../dist'),
            publicPath: '',
            libraryTarget: 'commonjs2'
        },
        module: {
            rules: [
                {
                    test: /.jsx$/,
                    loader: 'babel-loader'
                },
                {
                    test: /.js$/,
                    loader: 'babel-loader',
                    exclude: [
                        path.join(__dirname,'../node_modules')
                    ]
                }
            ]
        }
    }

4.在package.json中添加build:server为打包服务端文件。build打包前后端文件。

    "build:server": "webpack --config build/webpack.config.server.js",
    "build": "build:client && build:server"

5.从上面打包看,每次打包的文件都没有覆盖。为了覆盖之前打包的文件,安装rimraf。同时在在package.json中配置。

    npm i rimraf -D
    
    ...省略
    "clear": "rimraf dist",
    "build": "npm run clear && npm run build:client && npm run build:server"

6.以上服务端配置就ok了。可以开始写服务端express代码了。创建server目录,在server目录下创建server.js

    mkdir server
    cd server
    touch server.js

7.安装express

    npm i express -S

8.在server.js中写express代码

    const express = require('express')
    const ReactSSR = require('react-dom/server')
    const serverEntry = require('../dist/server-entry').default
    
    const app = express()
    
    app.get('*',(req,res)=>{
        const data = ReactSSR.renderToString(serverEntry)
        res.send(data)
    })
    
    app.listen('3333',()=>{
        console.log('server is listening on 3333')
    })

9.运行npm run build 和 npm start ,在127.0.0.1:3333上就能看到显示在页面上的内容了。但是这只是在js中输出的,并没有放到html的body里面。下面操作来将内容放到body。

  • 1.在client目录下创建template.html
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
  </head>
  <body>
      <div id="root">
          <app></app>
      </div>
  </body>
  </html>
  • 2.修改client目录下app.js。将document.body改为document.getElementById('root')。这样是将html渲染到id为root的div下面。
  • 3.将template.html整体渲染,在webpack.config.client.js指定到template.html
  plugins:[
      new HTMlPlugin({
          template:path.join(__dirname,'../client/template.html')
      })
  ]
  • 4.在server/server.js里面读取打包后的dist/index.html。用fs模块去读index.html,把读取的内容send出去。
  const express = require('express')
  const ReactSSR = require('react-dom/server')
  const serverEntry = require('../dist/server-entry').default
  const fs = require('fs')
  const path = require('path')
  
  //新增
  const template = fs.readFileSync(path.join(__dirname,'../dist/index.html'),'utf8')
  
  //新增,为了不让打包后的js文件返回html内容。
  需要同时将webpack.config.client.js和
  webpack.config.server.js里面的publicPath设置为public
  
  const app = express()
  app.use('/public',express.static(path.join(__dirname,'../dist')))
  
  app.get('*',(req,res)=>{
      const data = ReactSSR.renderToString(serverEntry)
      //新增
      res.send(template.replace('<app></app>',data))
  })
  
  app.listen('3333',()=>{
      console.log('server is listening on 3333')
  })

以上就配置好服务端渲染了。但是有个问题,每次修改都需要npm run build打包一下,npm start重启下服务。这样在实际工作中很浪费时间。下一篇文章中,我们会解决这个问题。