В Next JS как построить при обращении к внешнему npm пакету, содержащему SVG? - PullRequest
1 голос
/ 19 февраля 2020

Мой следующий js проект (назовем его TheHost) ссылается на другой npm пакет (назовем его ThePackage).

SVG нормально загружаются, когда определены в TheHost, но импорт ThePackage завершается неудачно, потому что next пытается интерпретировать svg как javascript ..., поэтому я получаю следующую ошибку при выполнении next build:

SyntaxError: Unexpected token '<'

Чтобы повторить, SVG отлично работают при обращении к svg, определенному в самом TheHost. Кажется, проблема заключается в импорте npm пакетов, содержащих SVG.

Не имеет значения, импортирую ли я компонент из ThePackage, использующий SVG, или нет, только тот факт, что где-то в пакете npm он содержит "import xxx from '../path/to/svg', чтобы сломать next build.

Для чего стоит ThePackage, javascript читает svg следующим образом:

var _mysvg = require("../path/to/the-svg.svg");

Множество деталей:

Следующая трассировка стека сборки:

> Using external babel configuration
> Location: "/Users/w/dev/TheHost/.babelrc"
Creating an optimized production build

Compiled successfully.

> Build error occurred
/Users/w/dev/TheHost/node_modules/ThePackage/build/assets/card_background.svg:1
<svg viewBox="0 0 860 382" fill="none" xmlns="http://www.w3.org/2000/svg">
^

SyntaxError: Unexpected token '<'
    at Module._compile (internal/modules/cjs/loader.js:895:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/Users/w/dev/TheHost/node_modules/TheProject/build/card/style.js:14:47)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32) {
  type: 'SyntaxError'
}
Automatically optimizing pages .%

Файл .babelr c:

{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    "babel-plugin-styled-components",
    "inline-react-svg"
  ]
}

Файл next.config. js:

const withSourceMaps = require("@zeit/next-source-maps");
const withImages = require("next-images");

module.exports = withImages(
  withSourceMaps({
    env: { *** redacted *** },
    publicRuntimeConfig: { *** redacted *** },
    webpack: (config, options) => {
      if (!options.isServer) {
        config.resolve.alias["@sentry/node"] = "@sentry/browser";
      }
      config.module.rules.push({
        test: /\.svg$/,
        use: ["@svgr/webpack"]
      });
      return config;
    }
  })
);

Следующие версии пакета js svgr имеют следующий вид:

"next": "^9.2.1",
"next-images": "^1.3.0",
"@svgr/webpack": "^5.1.0",
"babel-eslint": "^10.0.3",
"babel-plugin-inline-react-svg": "^1.1.1",

ThePackage построен со следующей конфигурацией вывода (webpack ):

  entry: './src/index.js',
  output: {
    path: buildFolder,
    filename: 'ThePackage.js',
    library: 'ThePackage',
    libraryTarget: 'umd', /* Note: umd */
    umdNamedDefine: true
  },

1 Ответ

4 голосов
/ 20 февраля 2020

Далее JS по умолчанию игнорирует node_modules, поэтому вам нужно специально разрешить вашей конфигурации возможность переносить ваш пакет. К счастью, кто-то уже создал плагин Next JS, чтобы разрешить это: https://github.com/martpie/next-transpile-modules

Я бы также предложил использовать Next Compose Plugins для очистки конфигурации. В итоге ваш next.config. js будет выглядеть примерно так:

const withSourceMaps = require("@zeit/next-source-maps");
const withImages = require("next-images");
const withPlugins = require('next-compose-plugins');
const withTM = require('next-transpile-modules')(['ThePackage']);

module.exports = withPlugins([
    withTM,
    [
        withImages,
        {
            exclude: /\.svg$/
        }
    ],
    withSourceMaps
],
{
    env: { *** redacted *** },
    publicRuntimeConfig: { *** redacted *** },
    webpack: (config, options) => {
      if (!options.isServer) {
        config.resolve.alias["@sentry/node"] = "@sentry/browser";
      }
      config.module.rules.push({
        test: /\.svg$/,
        use: ["@svgr/webpack"]
      });
      return config;
    }
});

Я также исключил обработку SVG с помощью withImages.

...