kzaiwo
kzaiwo

Reputation: 1768

FS - Use FS for Electron on Webpack 5

I recently upgraded my Quasar framework to v2 which uses Vue3, Electron 16 and Webpack 5.

When I tried to run my application, I keep getting this error:

Module not found: Can't resolve imported dependency "fs"

I understand that webpack 5 does not automatically do polyfills so I added these in my quasar.conf.js:

      chainWebpack (chain) {
        const nodePolyfillWebpackPlugin = require('node-polyfill-webpack-plugin')
        chain.plugin('node-polyfill').use(nodePolyfillWebpackPlugin)
      }

But this doesn't support polyfills for the fs module.

When I tried adding this:

        if (!cfg.resolve.fallback) {
          cfg.resolve.fallback = {}
          cfg.resolve.fallback.fs = false
        }

Now I get an error:

TypeError: fs.readFileSync is not a function

I also tried adding this in my package.json, same behavior (as expected):

  "browser": {
    "fs": false
  }

But then.. How can I use fs in my electron application?

Upvotes: 2

Views: 3862

Answers (3)

Raddish IoW
Raddish IoW

Reputation: 467

There is a new flag in Webpack 5 to target the build for Electron, which includes the correct support. Simply add target = 'electron-main' to your webpack config.

See more here: https://webpack.js.org/configuration/target/

Upvotes: 0

You can solve Can't resolve imported dependency "fs" error by adding the code below to "build" section in quasar.conf.js:

extendWebpack(cfg) {
  cfg.resolve.fallback = {
    fs: false
  }
}

quasar.conf.js:

module.exports = configure(function (ctx) {
  return {
    build: {
      extendWebpack(cfg) {
        cfg.resolve.fallback = {
          fs: false
        }
      } 
    }
  }
});

In addition, if there are more Can't resolve imported dependency "crypto", "Buffer", "os", "path", "stream", "assert" and so on, you can add them as shown below:

quasar.conf.js:

module.exports = configure(function (ctx) {
  return {
    build: {
      extendWebpack(cfg) {
        cfg.resolve.fallback = {
          fs: false,
          crypto: false,
          Buffer: false,
          os: false,
          path: false,
          stream: false,
          assert: false,
          dns: false,
          net: false,
          tls: false,
          http2: false,
          https: false,
          http: false,
          zlib: false
        }
      } 
    }
  }
});

"node-polyfill-webpack-plugin" cannot cover all Can't resolve imported dependency "xxx" errors and if you fully use my solution above, you don't need to use "node-polyfill-webpack-plugin". In other words, you can use "node-polyfill-webpack-plugin" to cover some parts of Can't resolve imported dependency "xxx" errors then for the rest of Can't resolve imported dependency "xxx" errors, you use my solution above so you can use 2 solutions at the same time.

Upvotes: 2

kzaiwo
kzaiwo

Reputation: 1768

Was able to figure it out now. Adding it here in case anyone might need it in the future. I see a lot of people asking this question but got no resolution.

So.. I added this to electron-preload.js, since fs / built-in node modules are accessible via the renderer:

import { contextBridge } from 'electron'

const fs = require('fs')
contextBridge.exposeInMainWorld('electronFs', {
  readFileSync: fs.readFileSync,
  existsSync: fs.existsSync
  // Other fs methods here
})

And use it like this in Vue / JS / modules:

const fs = window.electronFs
const jsonContent = JSON.parse(fs.readFileSync(SOME_PATH))

Upvotes: 2

Related Questions