Estoy tratando de integrar componentes cargables en mi proyecto SSR y funciona cuando ejecuté en localhost: 3000, luego intenté implementarlo en la función de nube. Recibo este error.
[ERR_INVALID_ARG_TYPE]: El argumento "ruta" debe ser de tipo cadena. Recibido indefinido
Después de eso, traté de implementar el ejemplo de representación del lado del servidor de componentes cargables , el código de muestra también dio el mismo error.
Hice algunos cambios en el archivo package.json, server main.js y app.js para trabajar en las funciones de la nube
Este es el archivo main.js de mi servidor
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); En este archivo hice estos cambios desde el código de ejemplo app.listen hasta export.supercharged exports.supercharged = functions.https.onRequest(app); e const functions = require('firebase-functions');
Este es mi archivo 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" } }En el archivo del paquete, reemplacé el script babel para copiar archivos a la carpeta de funciones en lugar de lib
"build:functions": "babel -d functions src",Aquí está mi aplicación.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 AppLos componentes cargables tienen mucho código en app.js, así que simplemente reemplacé app.js con un simple texto de hola mundo
Aquí está mi archivo firebase.json
{ "hosting": { "public": "public", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "function": "supercharged" } ] } }Todos estos son los cambios que realicé en el ejemplo del nodo asíncrono de representación del lado del servidor de componentes cargables
No sé lo que me perdí aquí, ayúdenme si me perdí o necesito agregar algo
Como ha señalado @hilipati, __dirname no está definido. Pero hay una solución más simple a ese problema, que se encuentra aquí
Antes de usar __dirname , puede sobrescribir el comportamiento predeterminado como
if(!__dirname) { __dirname = path.resolve(path.dirname('')); }o alternativamente
if(!__dirname) { __dirname = path.resolve(); }Según mi lectura de la documentación de la ruta, no es necesario proporcionar __dirname a path.resolve() . Resolverá la ruta absoluta para cualquier ruta relativa dada, incluso si no se proporcionan parámetros.
path.resolve(); // => '/root_path/current_working_directory'Con una ruta relativa:
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.jsonLas excepciones a esta regla son cuando ingresa rutas no relativas/absolutas como parámetros. Luego intentará resolver la ruta de derecha a izquierda hasta que se forme una ruta válida:
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'Entonces, su código resuelto debería verse de la siguiente manera:
const nodeStats = path.resolve('../../public/dist/async-node/loadable-stats.json') const webStats = path.resolve('../../public/dist/web/loadable-stats.json') Esto le dará /Volumes/React-Project/SSRAsync/public/dist/async-node/loadable-stats.json y /Volumes/React-Project/SSRAsync/public/dist/web/loadable-stats.json respectivamente. Esto sigue siendo cierto hasta el Nodo 16.x
Compruébelo al degradar el paquete web a 4.31.0, los componentes cargables tienen algunos problemas con el paquete web 5
"webpack": "^4.31.0", "webpack-cli": "^3.3.2", "webpack-dev-middleware": "^3.6.2", "webpack-node-externals": "^1.7.2"