Volto D3 Import Errors

Using external ''d3-org-chart" module in your volto project and importing it in your views with import { OrgChart } from 'd3-org-chart' results in following error.

Am not sure if this is result of webpack error or something far simpler.

node_modules/d3-org-chart/src/d3-org-chart.js:1
import { selection, select } from "d3-selection";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.d3-org-chart (/Code/frontend/external "d3-org-chart":1:1)
    at __webpack_require__ (/Code/frontend/build/webpack:/webpack/bootstrap:754:1)
    at fn (/Code/frontend/build/webpack:/webpack/bootstrap:59:1)

The problem is that, for some reason, d3-org-chart is installed in non-transpiled form.

./node_modules/.bin/babel --presets="@babel/env" node_modules/d3-org-chart --out-dir node_modules/d3-org-chart

This will "manually transpile" that module. (remove the node_modules/d3-org-chart folder and run yarn again, if things don't work out).

1 Like

Just to finish documenting this issue, there's another solution to the problem, but it's more "advanced".

It involves customizing your razzle.config.js (I know it's hard, I've added a ticket ) and adding something like this:

const path = require('path');
const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder');

// ... (inside the razzle.config modify function)
  const babelLoaderFinder = makeLoaderFinder('babel-loader');
  const babelLoader = config.module.rules.find(babelLoaderFinder);
  const { include } = babelLoader;

  const d3Path = path.dirname(require.resolve('d3-org-chart'));

  pkgs.forEach((name) => {
    include.push(d3Path);
  });

This adds the d3 package path to Babel's include paths, which happens automatically for all Volto addons, but not for anything that's not an addon.

1 Like

Thank you @tiberiuichim for following up. I noticed that the razzle.config.js in my current volto site is outdated. This might be due to the fact that it was generated quite a few volto versions ago.

/**
 * Replace with custom razzle config when needed.
 * @module razzle.config
 */
const fs = require('fs');

let voltoPath = './node_modules/@plone/volto';

let configFile;
if (fs.existsSync(`${this.projectRootPath}/tsconfig.json`))
  configFile = `${this.projectRootPath}/tsconfig.json`;
else if (fs.existsSync(`${this.projectRootPath}/jsconfig.json`))
  configFile = `${this.projectRootPath}/jsconfig.json`;

if (configFile) {
  const jsConfig = require(configFile).compilerOptions;
  const pathsConfig = jsConfig.paths;
  if (pathsConfig['@plone/volto'])
    voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`;
}

module.exports = require(`${voltoPath}/razzle.config`);

I think I should finish update it to upstream version in volto site before making the changes you suggested?

I think your razzle.config.js is fine, here's the Volto template for projects: volto/razzle.config.js at 4a760bde9bc2ea8050d7a16f2b518e244d415536 · plone/volto · GitHub

1 Like