[英]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.