Reputation: 27027
My nextjs project (let's call it TheHost) references another npm package (let's call it ThePackage).
SVGs load fine when defined within TheHost, but importing ThePackage fails because next tries to interpret the svg as javascript... so I get the following error when doing a next build
:
SyntaxError: Unexpected token '<'
To re-iterate, SVGs work fine when referencing an svg defined in TheHost itself. The problem seems to be importing npm packages that contain SVGs.
It doesn't matter if I import a component from ThePackage that uses an SVG or not, just the fact that somewhere in the npm package it contains an "import xxx from '../path/to/svg' is enough to break next build
.
For what it's worth, the ThePackage's transpiled javascript reads the svg as follows:
var _mysvg = require("../path/to/the-svg.svg");
The next build stack trace is:
> 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 .%
The .babelrc file:
{
"presets": [
"next/babel"
],
"plugins": [
"babel-plugin-styled-components",
"inline-react-svg"
]
}
The next.config.js file:
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;
}
})
);
The nextjs svgr package versions are as follows:
"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 is built with the following output configuration (webpack):
entry: './src/index.js',
output: {
path: buildFolder,
filename: 'ThePackage.js',
library: 'ThePackage',
libraryTarget: 'umd', /* Note: umd */
umdNamedDefine: true
},
Upvotes: 10
Views: 9425
Reputation: 755
As stated in Seagyn's answer, NextJS ignores node_modules
by default and as a result @svgr/webpack
is not being run on the SVGs that are in the node_modules
, leading to your error.
As of NextJS Version 13 a transpilePackages
option was added to the next.config.js
which allows you to pass an array of packages that you want to be transpiled in addition to your source code.
All you have to do now is add the following to your next.config.js
:
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['ThePackage'], // <- Add this
}
module.exports = nextConfig
Add the package which includes the SVGs to that array and that should solve your issue.
You can see the docs here.
Upvotes: 1
Reputation: 146
NextJS ignores node_modules
by default so you'd need to specifically allow your config to be able to transpile your package. Fortunately, someone has already created a NextJS plugin to allow this: https://github.com/martpie/next-transpile-modules
I'd also suggest using Next Compose Plugins to neaten up the config. In the end, your next.config.js will look something like this:
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;
}
});
I've also excluded SVGs from being processed by withImages
.
Upvotes: 13