React ssr框架Next.js 的生产实践

大桔子
首先感慨一句,next 真是一个版本狂人啊,一周就一个小版本

1. 按照官网的方式初始化一个Next.js项目遇到的一些问题

  • 默认初始化的框架样式支持sass,组件级别的[name].module.css,但默认不支持less,官方提供了配置less的方法

    `yarn add @zeit/next-less less`
    // next.config.js
    const withLess = require('@zeit/next-less')
    module.exports = withLess({
      webpack(config, options) {
          config.resolve = {
              alias: {
                ...config.resolve.alias,
                // 配置alias同时要在tsconfig.json 配置 baseUrl,paths
                "@": path.resolve(__dirname, ".") 
              },
              extensions: [".ts", ".tsx", ".js", ".jsx", ".less", ".css"]
        };
        return config
      }
    })

    重新启动后会报 Error: Cannot find module 'webpack' 于是就安装webpack但默认安装的是webpack@5.x,按照这个 issue,要替换成 webpack@4.x 才可以

  • Next.js 打包后静态资源路径中的 _next 目录哪来的 ?
    参考此文
    打包配置 配置assetPrefix,相当于webpack里面的publicPath(将静态资源放在cdn)
    但打包后html引入的静态资源地址会多一层_next目录,解决方案:
    自己代码里创建 _next 目录太过繁琐,且消耗性能,故让运维在拷贝静态资源时,在oss目录上多加一层 _next 目录
  • ssr框架 ajax 请求库的选择node-fetchwindow, document的使用注意事项
  • getInitialProps getStaticProps getStaticPaths getServerSideProps区别
  • clint Link 跳转时子页面样式文件获取不到(好像只有开发阶段有次问题,暂时未解决)
  • 当进行重构项目时,如果不想改变老项目的url(可能由于url已经被百度seo收录),可以利用自定义node服务器,将老url转发到新的url,参考文档但是有个问题这种被转发的url为什么浏览器请求会是 404,但页面还是会正常显示,不知道是为什么???

2. 生产部署

  • 接入公司cicd规范,部署没有使用传统的pm2,而是把服务放在一个容器内,服务重启靠node提供一个健康检查接口,容器来保证服务稳定,当该接口没有正常返回docker容器就会重启应用
  • 由于公司规范启动node服务都是在容器内用 node app.js,但next默认启动是靠next start启动生产服务的。解决方案是:next提供了自定义服务器,我这里采用了koa,将next作为一个中间件来处理参考

    // https://www.nextjs.cn/docs/advanced-features/custom-server
    const Koa = require('koa') // 引入 koa
    const next = require('next') // nextjs 作为中间件
    const routesMap = require('./route') // 新老url冲突时,将老url转发
    
    const dev = process.env.NODE_ENV === 'development' // 判断是否处于开发者状态
    const app = next({ dev }) // 初始化 nextjs,判断它是否处于 dev:开发者状态,还是production: 正式服务状态
    const handle = app.getRequestHandler() // 拿到 http 请求的响应
    
    console.log('next dev环境===>', dev)
    
    const port = 8080
    
    // app.prepare:编译 pages 文件夹下面的页面文件,then 是保证 pages 下页面全部编译完了之后,我们才能真正的启动服务来响应请求。
    // 如果这些内容我们没有编译完成,那么启动服务响应请求的时候可能会报错。
    app.prepare().then(() => {
      const server = new Koa() // 声明一个 server
    
      /** 这是 Koa 的核心用法:中间件。通常给 use 里面写一个函数,这个函数就是中间件。
       * params:
       *  ctx: Koa Context 将 node 的 request 和 response 对象封装到单个对象中,为请求上下文对象
       *  next: 调用后将执行流程转入下一个中间件,如果当前中间件中没有调用 next,整个中间件的执行流程则会在这里终止,后续中间件不会得到执行
       */
      server.use(async (ctx, next) => {
        if (routesMap[ctx.path]) {
          // 老url转发~~~~,这种操作页面可以正常出来,但不知道为什么浏览器状态码会是404
          await app.render(ctx.req, ctx.res, routesMap[ctx.path])
        } else {
          await handle(ctx.req, ctx.res)
        }
        ctx.response = false
      })
    
      server.listen(port)
      console.log(`请访问: http://localhost:${port}`)
    })
阅读 1.3k

大桔子
在2017年成为一名合格的前端攻城狮狮狮

下一步该干什么呢...

543 声望
42 粉丝
0 条评论
你知道吗?

下一步该干什么呢...

543 声望
42 粉丝
文章目录
宣传栏