美文网首页
umijs使用服务器端渲染ssr

umijs使用服务器端渲染ssr

作者: 第2世界 | 来源:发表于2020-02-06 22:49 被阅读0次

    server.js demo 文章已更新,请看下面更新之后的内容
    使用官网上教程中的代码有点问题,自己参照实例改了下,修改了个express的ssr server。如果使用的话注意把其中dist改成你build之后的目录名。

    require('regenerator-runtime/runtime');
    const server = require('umi-server');
    const express = require('express');
    const compression = require('compression');
    const helmet = require('helmet');
    const { join, extname } = require('path');
    const { createReadStream } = require('fs');
    
    const isDev = process.env.NODE_ENV === 'development';
    
    const root = join(__dirname, 'dist');
    const render = server({
      root,
      polyfill: false,
      dev: isDev,
    });
    
    const app = express();
    app.use(compression());
    app.use(helmet());
    // app.use('.', express.static(root));
    
    app.get('*', async (req, res, next) => {
      const headerMap = {
        '.js': 'text/javascript',
        '.css': 'text/css',
        '.jpg': 'image/jpeg',
        '.png': 'image/jpeg',
      }
      const ext = extname(req.url);
      const header = {
        'Content-Type': headerMap[ext] || 'text/html'
      }
      if (!ext) {
        const { ssrHtml } = await render({
          req: {
            url: req.originalUrl,
          },
        });
        res.status(200).send(ssrHtml);
      } else {
        // static file url
        const path = join(root, req.url);
        res.sendFile(path);
      }
    });
    
    if (!process.env.NOW_ZEIT_ENV) {
      app.listen(8080);
      console.log('http://localhost:8080');
    }
    
    module.exports = app;
    
    

    需要安装包的package.json,里面乱七八糟,我也是新手,不敢随便删减...

    {
      "private": true,
      "scripts": {
        "build": "umi build",
        "server": "npm run build && nodemon server.js",
        "start": "cross-env NODE_ENV=development concurrently \"umi dev\" \"nodemon server.js\"",
        "debug": "cross-env RM_TMPDIR=none COMPRESS=none UMI_ENV=prod umi build && node server.js"
      },
      "dependencies": {
        "antd": "^3.19.5",
        "axios": "^0.19.2",
        "compression": "^1.7.4",
        "cross-env": "^5.2.0",
        "dva": "^2.6.0-beta.6",
        "express": "^4.17.1",
        "helmet": "^3.21.2",
        "lodash": "^4.17.15",
        "prettier": "^1.19.1",
        "prop-types": "^15.7.2",
        "react": "^16.8.6",
        "react-axios": "^2.0.3",
        "react-document-title": "^2.0.3",
        "react-dom": "^16.8.6",
        "regenerator-runtime": "^0.13.2",
        "roadhog-api-doc": "^1.1.2",
        "umi-request": "^1.2.4",
        "umi-server": "^1.0.0"
      },
      "devDependencies": {
        "@types/jest": "^23.3.12",
        "@types/react": "^16.7.18",
        "@types/react-dom": "^16.0.11",
        "@types/react-test-renderer": "^16.0.3",
        "babel-eslint": "^9.0.0",
        "eslint": "^5.4.0",
        "eslint-config-umi": "^1.4.0",
        "eslint-plugin-flowtype": "^2.50.0",
        "eslint-plugin-import": "^2.14.0",
        "eslint-plugin-jsx-a11y": "^5.1.1",
        "eslint-plugin-react": "^7.11.1",
        "husky": "^0.14.3",
        "lint-staged": "^7.2.2",
        "react-test-renderer": "^16.7.0",
        "umi": "^2.9.0",
        "umi-plugin-react": "^1.8.0",
        "umi-types": "^0.3.0"
      },
      "lint-staged": {
        "*.{ts,tsx}": [
          "eslint --fix",
          "git add"
        ],
        "*.{js,jsx}": [
          "eslint --fix",
          "git add"
        ]
      },
      "engines": {
        "node": ">=8.0.0"
      }
    }
    
    

    最后执行

    node server.js
    

    ====================================

    更新

    上面的做法确实可以执行,但是存在一个很大的问题,就是生成的umi-server.js仍然依赖开发时用的各种包,经过再次查看官方文档,找到了原因。

    https://umijs.org/zh/config/#ssr

    ssr beta 2.8.0+
    类型: Boolean | Object
    默认值: false
    用于服务端渲染(Server-Side Render)。
    开启后,生成客户端静态文件的同时,也会生成 umi.server.js 和 ssr-client-mainifest.json 文件。
    export default {
    ssr: {
    // https://github.com/liady/webpack-node-externals#optionswhitelist-
    externalWhitelist?: [];
    // webpack-node-externals 配置,排除 whiteList
    nodeExternalsOpts?: {};
    // 客户端资源 manifest 文件名,默认是 ssr-client-mainifest.json
    manifestFileName: 'ssr-client-mainifest.json',
    // 关闭 ssr external,全量打入 umi.server.js
    disableExternal: false,
    // 关闭 ssr external 时,白名单模块将进入 externa
    // 可用于 react-helmet, react-document-title
    disableExternalWhiteList?: string[] | object;
    },
    };

    我之前直接将ssr配置为true,可以生成ssr的文件,但是默认的配置disableExternal: false,它并不会把依赖的js全部打包进去,查看之前build之后的umi-server.js里面仍然有各种require。

    看完这个配置之后,我将.umirc.ts文件中的配置改为:

    import { IConfig } from 'umi-types'; // ref: https://umijs.org/config/
    
    const config: IConfig = {
      ssr: {
        disableExternal: true,
      },
      treeShaking: true,
      targets: {
        ie: 11,
      },
      ....//此处省略了,自己配置routes,plugins
    };
    export default config;
    

    然后重新打包 umi build生成的umi.server.js就不需要依赖其他的包了。

    回过头来再看https://umijs.org/zh/guide/ssr.html#%E6%9C%8D%E5%8A%A1%E7%AB%AF

    const server = require('umi-server');
    const http = require('http');
    const { createReadStream } = require('fs');
    const { join, extname } = require('path');
    
    const root = join(__dirname, 'dist');
    const render = server({
      root,
    })
    const headerMap = {
      '.js': 'text/javascript',
      '.css': 'text/css',
      '.jpg': 'image/jpeg',
      '.png': 'image/jpeg',
    }
    
    http.createServer(async (req, res) => {
      const ext = extname(req.url);
      const header = {
        'Content-Type': headerMap[ext] || 'text/html'
      }
      res.writeHead(200, header);
    
      if (!ext) {
        // url render
        const ctx = {
          req,
          res,
        }
        const { ssrHtml } = await render(ctx);
        res.write(ssrHtml);
        res.end()
      } else {
        // static file url
        const path = join(root, req.url);
        const stream = createReadStream(path);
        stream.on('error', (error) => {
          res.writeHead(404, 'Not Found');
          res.end();
        });
        stream.pipe(res);
      }
    
    }).listen(3000)
    
    console.log('http://localhost:3000');
    

    可以运行了,不会报错。只需要package.json里面有umi-server,然后npm install:

      "dependencies": {
        "umi-server": "^1.0.0"
      },
    

    搞定,好开心,官方的文档真坑,一个disableExternal: false,ssr:true把我坑惨了。

    相关文章

      网友评论

          本文标题:umijs使用服务器端渲染ssr

          本文链接:https://www.haomeiwen.com/subject/lfjpxhtx.html