简体   繁体   English

部署 React 时出现错误“路径”参数必须是字符串 - 云函数中的可加载组件示例代码

[英]Getting error "Path" argument must be string while deploying React - Loadable components sample code in cloud functions

I'm trying to integrate Loadable components in my SSR project and that is working when I executed in localhost:3000, then I tried to deploy it in cloud function I am getting this error我正在尝试将可加载组件集成到我的 SSR 项目中,并且当我在 localhost:3000 中执行时它正在工作,然后我尝试将它部署在云 function 中我收到此错误

[ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。 Received undefined收到未定义

After that I tried to deploy loadable components server side rendering example , sample code also giving the same error.之后我尝试部署可加载组件服务器端渲染示例,示例代码也给出了相同的错误。

I did some changes in package.json, server main.js and app.js file to work in Cloud functions我对 package.json、服务器 main.js 和 app.js 文件进行了一些更改,以便在云功能中工作

This is my server main.js file这是我的服务器 main.js 文件

import path from 'path'
import express from 'express'
import React from 'react'
import { renderToString } from 'react-dom/server'
import { ChunkExtractor } from '@loadable/server'
import App from '../client/App'
const functions = require('firebase-functions');
const app = express()


//app.use(express.static(path.join(__dirname, '../../public')))


const nodeStats = path.resolve(
  __dirname,
  '../../public/dist/async-node/loadable-stats.json',
)

const webStats = path.resolve(
  __dirname,
  '../../public/dist/web/loadable-stats.json',
)

app.get('*', (req, res) => {
  const nodeExtractor = new ChunkExtractor({ statsFile: nodeStats })
  const { default: App } = nodeExtractor.requireEntrypoint()

  const webExtractor = new ChunkExtractor({ statsFile: webStats })
  const jsx = webExtractor.collectChunks(<App />)

  const html = renderToString(jsx)

  res.set('content-type', 'text/html')
  res.send(`
      <!DOCTYPE html>
      <html>
        <head>
        ${webExtractor.getLinkTags()}
        ${webExtractor.getStyleTags()}
        </head>
        <body>
          <div id="main">${html}</div>
          ${webExtractor.getScriptTags()}
        </body>
      </html>
    `)
})

// eslint-disable-next-line no-console
exports.supercharged = functions.https.onRequest(app);

In this file I did these changes from example code app.listen to exports.supercharged = functions.https.onRequest(app);在这个文件中,我从示例代码app.listen到 export.supercharged exports.supercharged = functions.https.onRequest(app);做了这些更改。 and I imported the const functions = require('firebase-functions');我导入了const functions = require('firebase-functions');

This is my package.json file这是我的 package.json 文件

{
  "private": true,
  "scripts": {
    "dev": "nodemon src/server/main.js",
    "build": "NODE_ENV=production yarn build:webpack && yarn build:functions",
    "build:webpack": "webpack",
    "build:functions": "babel -d functions src",
    "start": "NODE_ENV=production node functions/server/main.js",
    "deploy": "firebase deploy --only functions,hosting",
    "serve": "firebase serve --only functions,hosting"
  },
  "devDependencies": {
    "@babel/cli": "^7.4.4",
    "@babel/core": "^7.6.2",
    "@babel/node": "^7.0.0",
    "@babel/preset-env": "^7.6.2",
    "@babel/preset-react": "^7.0.0",
    "@loadable/babel-plugin": "^5.10.3",
    "@loadable/component": "^5.10.3",
    "@loadable/server": "^5.10.3",
    "@loadable/webpack-plugin": "^5.7.1",
    "babel-loader": "^8.0.6",
    "css-loader": "^2.1.1",
    "mini-css-extract-plugin": "^0.6.0",
    "nodemon": "^1.19.0",
    "webpack": "^5.0.0-beta.16",
    "webpack-cli": "^3.3.2",
    "webpack-dev-middleware": "^3.6.2",
    "webpack-node-externals": "^1.7.2"
  },
  "dependencies": {
    "core-js": "^3.0.1",
    "express": "^4.16.4",
    "firebase-admin": "^9.2.0",
    "firebase-functions": "^3.11.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6"
  }
}

In package file I replaced babel script to copy files to functions folder instead of lib在 package 文件中,我替换了 babel 脚本以将文件复制到函数文件夹而不是 lib

"build:functions": "babel -d functions src", 

Here is my app.js这是我的 app.js

import React from 'react'
// eslint-disable-next-line import/no-extraneous-dependencies
import loadable from '@loadable/component'

const App = () => (
  <div>
  Hello world
  </div>
)

export default App

Loadable componets has lot of code in app.js so I just replaced app.js with simple hello world text可加载组件在 app.js 中有很多代码,所以我只是用简单的 hello world 文本替换了 app.js

Here is my firebase.json file这是我的 firebase.json 文件

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "supercharged"
      }
    ]
  }
}

These all are the changes I made from the the loadable-components server side rendering async node example这些都是我从可加载组件服务器端渲染异步节点示例中所做的更改

I don't know what I missed here, Please assist me if I missed or need to add anything我不知道我在这里错过了什么,如果我错过了或需要添加任何东西,请帮助我

From my reading of the documentation for path it is unnecessary to provide __dirname to path.resolve() .根据我对 path 文档的阅读,没有必要将__dirname提供给path.resolve() It will resolve the absolute path for any given relative path including if no parameters are given.它将解析任何给定相对路径的绝对路径,包括如果没有给出参数。

path.resolve(); // => '/root_path/current_working_directory'

With a relative path:使用相对路径:

const location = path.resolve('./your_relative_path/file.json')
// OR
const sameLocation = path.resolve('./your_relative_path', 'file.json')
// => '/root_path/current_working_directory/your_relative_path/file.json

Exceptions to this rule are where you enter a non relative/absolute paths as parameters.此规则的例外情况是您输入非相对/绝对路径作为参数。 Then it will attempt to resolve the path right to left until a valid path is formed:然后它将尝试从右到左解析路径,直到形成有效路径:

path.resolve('/your_absolute_path/file.json')
// OR
path.resolve('/your_absolute_path', 'file.json')
// => '/your_absolute_path/file.json'

path.resolve('/your_absolute_path', '/file.json')
// => '/file.json'

path.resolve('/one_path', '/another_path', 'file.json')
// => '/another_path/file.json'

So, your resolved code should look as follows:因此,您解析的代码应如下所示:

const nodeStats = path.resolve('../../public/dist/async-node/loadable-stats.json')

const webStats = path.resolve('../../public/dist/web/loadable-stats.json')

This will give you /Volumes/React-Project/SSRAsync/public/dist/async-node/loadable-stats.json and /Volumes/React-Project/SSRAsync/public/dist/web/loadable-stats.json respectively.这将分别为您提供/Volumes/React-Project/SSRAsync/public/dist/async-node/loadable-stats.json/Volumes/React-Project/SSRAsync/public/dist/web/loadable-stats.json This still holds true through to Node 16.x这仍然适用于 Node 16.x

Check by downgrading webpack to 4.31.0, Loadable components has some issues with webpack 5通过将 webpack 降级到 4.31.0 进行检查,可加载组件与 webpack 存在一些问题 5

"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-middleware": "^3.6.2",
"webpack-node-externals": "^1.7.2"

It seems the __dirname is not defined.似乎__dirname没有定义。 You can get the same error with a simple require('path').resolve(undefined, '..') .您可以使用简单的require('path').resolve(undefined, '..')得到相同的错误。

That happens for ECMAScript modules (see eg issue ). ECMAScript 模块会发生这种情况(参见例如issue )。

You can try你可以试试

import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

as instructed in one of the linked issue's answers.按照链接问题的答案之一的指示。

As @hilipati has pointed out, __dirname is not defined.正如@hilipati 指出的那样, __dirname没有定义。 But there is a more simple solution to that issue, found here但是这个问题有一个更简单的解决方案,在这里找到

Before using __dirname , you can overwrite the default behaviour like在使用__dirname之前,您可以覆盖默认行为,例如

if(!__dirname) {
    __dirname = path.resolve(path.dirname(''));
}

or, alternatively或者,或者,

if(!__dirname) {
    __dirname = path.resolve();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我收到 First argument "email" must be a valid string error while firebase authentication in react - I am getting First argument "email" must be a valid string error while firebase authentication in react 部署 Firebase 云发布订阅代码时出错 - getting error while deploying firebase cloud pub-sub code 部署Firebase云功能时发生意外错误 - Unexpected error while deploying firebase cloud functions 错误:“路径”参数必须是字符串类型。 收到未定义。 firebase deploy --only 功能 - Error: The “path” argument must be of type string. Received undefined. firebase deploy --only functions 错误:在部署云功能时解析触发器时出错 - Firebase - Error: Error parsing triggers while deploying cloud functions - Firebase 测试可反应加载的组件 - Testing react-loadable components 获取错误:verifyIdToken() 的第一个参数必须是 Firebase ID 令牌字符串 - Getting Error: First argument to verifyIdToken() must be a Firebase ID token string 使用react-loadable进行代码拆分会产生错误:找不到模块“。” - Code Splitting with react-loadable gives Error : Cannot find module “.” 为什么反应组件作为 class 必须有`render`方法,而那些作为函数没有? - Why do react components as class must have `render` method, while those as functions don't? 当我尝试在Windows中通过cmd执行代码时,我不断收到“路径必须是缓冲区的字符串”错误 - I keep getting “Path must be a string of buffer” error when I try to execute my code through cmd in Windows
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM