Blitz: Module not found: Can't resolve 'fs'

Created on 29 Nov 2020  路  14Comments  路  Source: blitz-js/blitz

I have on a page a mutation. If I go to the page (not using the mutation) I get the error, just by visiting the page.
Module not found: Can't resolve 'fs'

import { Ctx } from "blitz"
import db, { Prisma } from "db"

var fs = require("fs")

type DeleteFileInput = Pick<Prisma.FileDeleteArgs, "where">

export default async function deleteFile({ where }: DeleteFileInput, ctx: Ctx) {
  ctx.session.authorize()

  const pathDelete = `../../../public${where.src}`

  fs.stat(pathDelete, function (err, _stats) {
    if (err) {
      return console.error(err)
    }

    fs.unlink(pathDelete, function (err) {
      if (err) return console.log(err)
      console.log("file deleted successfully")
    })
  })

  await db.file.delete({ where })

  return true
}

I'm using "blitz": "0.26.2", in "blitz": "0.25.0", I hade the same mutation without any problems.
I have this error after I updated to the newest version
I mean fs is just aviable on the server. But the mutaion is on the server. So I don't get why I get the error instant when I visit a page where I use the deleteFile mutation.

kinbug statudone

All 14 comments

I removed the the fs-part to a API-Route and now it is working.
So I guess the mutation runs on the client side. But again in blitz": "0.25.0" is was working

I removed the the fs-part to a API-Route and now it is working.
So I guess the mutation runs on the client side. But again in blitz": "0.25.0" is was working

How did you do that? using fetch at the end?

file/mutations/deletFile.ts

import { Ctx } from "blitz"
import db, { Prisma } from "db"

type DeleteFileInput = Pick<Prisma.FileDeleteArgs, "where">

export default async function deleteFile({ where }: DeleteFileInput, ctx: Ctx) {
  ctx.session.authorize()

  await fetch("http://localhost:3000/api/deleteFileFs", {
    method: "post",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      src: where.src,
    }),
  })
    .then((success) => {
      console.log(success)
    })
    .catch((error) => console.log(error))

  await db.file.delete({ where })

  return true
}

/api/deleteFileFs.ts

import { handleRequestWithMiddleware, BlitzApiResponse, BlitzApiRequest } from "blitz"
var fs = require("fs")

const handleApi = async (req: BlitzApiRequest, res: BlitzApiResponse) => {
  const { src } = req.body

  const pathDelete = `../../../public${src}`

  fs.stat(pathDelete, function (err, _stats) {
    if (err) {
      return console.error(err)
    }

    fs.unlink(pathDelete, function (err) {
      if (err) return console.log(err)
      console.log("file deleted successfully")
    })
  })

  res.send("ok")
}

const handler = async (req: BlitzApiRequest, res: BlitzApiResponse) => {
  handleRequestWithMiddleware(req, res, [handleApi])
}

export default handler

@vonphlpp This is awesome man. thanks for sharing. 馃檹

Keep in mind that at the /api/deleteFileFs.ts the authentication is missing. I will make a middleware later....

I can confirm that both queries and mutations are being built on the client as well. Happens with 0.26.2. Doesn't happen on 0.25.0.

Sorry about this folks, definitely a bug. Here's a workaround:

Add the following to blitz.config.js and change excluded to match anything that's causing you problems

  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.module = config.module || {}
      config.module.rules = config.module.rules || []
      const excluded = [
        /mailers/,
        /tslog/,
        /utils\/logger/,
      ]
      excluded.forEach((excluded) => {
        config.module.rules.push({ test: excluded, use: { loader: "null-loader" } })
      })
    }
    return config
  }

Nice one Brandon

I don't understand how to use this workaround, I added my mutations to excluded and it would not compile.

@zenhob you have to add the node_module dependencies that are causing problems. If you post your entire error stack trace, I can tell you want to exclude

I'm sure its something simple. I am excluding the Twilio node.js library:

  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.module = config.module || {}
      config.module.rules = config.module.rules || []
      const excluded = [/node_modules\/twilio\//]
      excluded.forEach((excluded) => {
        config.module.rules.push({ test: excluded, use: { loader: "null-loader" } })
      })
    }
    return config
  }

My build now completes but my page fails to load an unrelated lib secure_password:

secure_password__WEBPACK_IMPORTED_MODULE_3___default.a is not a constructor

@zenhob I'm getting the same error on my end.

@zenhob I think @flybayer already came up with a solution for this. See here: https://github.com/blitz-js/blitz/issues/1545#issuecomment-734984034

Fixed in 0.27.0!

Was this page helpful?
0 / 5 - 0 ratings