Search code examples
javascripttypescriptwebpackelectronjs-ipfs

Cannot find module 'jsonfile/utils' in Electron-Typescript app


I started from a brand new working very simple Electron-Typescript app.

In this working really simple Electron-Typescript app, I added in main.ts:

import Ipfs from 'ipfs';
import IpfsHttpClient from 'ipfs-http-client';

and this import of ipfs modules went fine.

But when I add

const { globSource } = IpfsHttpClient;

or

when I create an IPFS node:

const ops = async () => {
  const node = await Ipfs.create({ repo: String(Math.random() + Date.now()) });
}

I get this error:

A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'jsonfile/utils'
    at webpackMissingModule (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:13356:87)
    at Object../node_modules/fs-extra/lib/json/output-json.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:13356:176)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/fs-extra/lib/json/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:13284:25)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/fs-extra/lib/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:13250:6)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/ipfs-utils/src/files/glob-source.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:25171:12)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/ipfs-http-client/src/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:21670:20)

tools/webpack/webpack.main.js :

module.exports = {
  entry: ['./src/main.ts'],
  // Put your normal webpack config below here
  module: {
    rules: require('./webpack.rules'),
  },
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
    alias: require('./webpack.aliases'),
  },
  target: 'electron-main'
};

tools/webpack/webpack.renderer.js :

/* eslint-disable @typescript-eslint/no-var-requires */
const rules = require('./webpack.rules');
const plugins = require('./webpack.plugins');
const aliases = require('./webpack.aliases');

module.exports = {
  target: 'electron-renderer',
  module: {
    rules,
  },
  plugins: plugins,
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
    alias: {
      // React Hot Loader Patch
      'react-dom': '@hot-loader/react-dom',
      // Custom Aliases
      ...aliases,
    },
  },
};

tools/webpack/webpack.rules.js :

const inDev = process.env.NODE_ENV === 'development';

module.exports = [
  {
    // Add support for native node modules
    test: /\.node$/,
    use: 'node-loader',
  },
  {
    // Typescript loader
    test: /\.tsx?$/,
    exclude: /(node_modules|\.webpack)/,
    use: {
      loader: 'ts-loader',
      options: {
        transpileOnly: true,
      },
    },
  },
  {
    // CSS Loader
    test: /\.css$/,
    use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
  },
  {
    // Less loader
    test: /\.less$/,
    use: [
      { loader: 'style-loader' },
      { loader: 'css-loader' },
      { loader: 'less-loader' },
    ],
  },
  {
    // Images Loader
    test: /\.(gif|jpe?g|tiff|png|webp|bmp)$/,
    use: [
      {
        loader: 'file-loader',
        options: {
          publicPath: 'images',
          outputPath: inDev ? 'images' : './main_window/images',
        },
      },
    ],
  },
];

If modify the target from electron-renderer' to web' in tools/webpack/webpack.renderer.js :

/* eslint-disable @typescript-eslint/no-var-requires */
const rules = require('./webpack.rules');
const plugins = require('./webpack.plugins');
const aliases = require('./webpack.aliases');

module.exports = {
  //target: 'electron-renderer',
  target: 'web',
  module: {
    rules,
  },
  plugins: plugins,
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
    alias: {
      // React Hot Loader Patch
      'react-dom': '@hot-loader/react-dom',
      // Custom Aliases
      ...aliases,
    },
  },
};

And in the renderer process /src/app/components/App.tsx I add :

import Ipfs from 'ipfs';
const { globSource } = Ipfs;

const ops = async () => {
    const node = await Ipfs.create({ repo: String(Math.random() + 
Date.now()) });
    console.log('Ipfs node is ready');
    const files = [
      {
        path: '/home/marco/Downloads/Art21Costituzione.jpg',
        content: 'Art21Costituzione'
      },
      {
        path: '/home/marco/Downloads/VitaminaCAlimenti.pdf',
        content: 'VitaminaCAlimenti'
      }
    ];

    let results = await all(node.addAll(files));
    results.map(result => console.log(result));
}

I get this correct output:

enter image description here

But globSource in the renderer process gives error:

for await (const file of node.addAll(globSource('/home/marco
/Downloads', globSourceOptions), addOptions)) {
  console.log(file);
}

enter image description here

So.. I guess there is something to fix in webpack configuration in order to make it work in the main process, instead of having it in the renderer process.

How to solve the problem?


Solution

  • Just install jsonfile

    yarn add jsonfile
    

    worked for me! https://www.npmjs.com/package/jsonfile