Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

[ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. 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

This is my server main.js file

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); and I imported the const functions = require('firebase-functions');

This is my package.json file

{
  "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

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

Here is my 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

Here is my firebase.json file

{
  "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

like image 568
Curvegraph Avatar asked May 21 '21 03:05

Curvegraph


Video Answer


2 Answers

Check by downgrading webpack to 4.31.0, Loadable components has some issues with webpack 5

"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-middleware": "^3.6.2",
"webpack-node-externals": "^1.7.2"
like image 112
MathankumarK Avatar answered Oct 08 '22 13:10

MathankumarK


From my reading of the documentation for path it is unnecessary to provide __dirname to 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. This still holds true through to Node 16.x

like image 34
jfgilmore Avatar answered Oct 08 '22 15:10

jfgilmore