NextJS styled-components giving an error in bundle file - javascript

I am using styled-components for my React project. After I bundled my react application with rollupjs then I am trying to use this bundle with NextJS. It is getting error in NextJS:
ReferenceError: window is not defined
When I look line of error in the bundle file this error is happening inside of styled-components.
Here is my rollup.config.js in React App (not Nextjs):
import babel from "rollup-plugin-babel";
import commonjs from "#rollup/plugin-commonjs";
import external from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import resolve from "#rollup/plugin-node-resolve";
import image from "#rollup/plugin-image";
import visualizer from "rollup-plugin-visualizer";
import pkg from "./package.json";
// PostCSS plugins
import simplevars from "postcss-simple-vars";
import nested from "postcss-nested";
import cssnext from "postcss-cssnext";
import cssnano from "cssnano";
import cssvariables from "postcss-css-variables";
const extensions = [".js", ".jsx", ".ts", ".tsx"];
export default {
input: ["./src/index.js"],
output: [
{
file: pkg.main,
format: "cjs",
globals: { react: "React" },
},
{
file: pkg.module,
format: "esm",
},
],
plugins: [
external(["react", "uikit"]),
postcss({
plugins: [
simplevars(),
cssvariables(),
nested(),
cssnext({ warnForDuplicates: false }),
cssnano(),
],
extensions: [".css"],
}),
babel({
exclude: "node_modules/**",
extensions,
}),
// Allows node_modules resolution
resolve({
mainFields: ["module", "main", "jsnext:main", "browser"],
dedupe: ["react", "react-dom"], // Default: []
extensions,
}),
commonjs(),
image(),
visualizer(),
],
};
How can I solve this error in NextJS with bundle code?
Thanks

It means your window related code is executed on the Node.js side, not on the browser. Since Next.js is server-side rendering framework, you should make sure that you don't use browser thing (like window object) in the code that is executed on the server side.
Please reference this article.
UPDATE
Please check your .babelrc -
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}

Related

Rollup UMD Module Reference to Named Imports is Undefined

I had a published component library (my-components) that had a specific component (Compare) in it, along w/ other components and utilities that were used in a main application. We use rollup and create several different output formats, one of which is UMD (required by one of the teams using my-components).
The component (Compare) was starting to become large, so it was moved out on its own. The rollup build was based off of what was used for my-components. After moving it out to its own repository to be built as its own component, it now had a dependency on my-components. When used in the main application (CRA app), everything works as expected. However, when the team who uses the UMD module tried to use the Compare app, they started to get errors:
Cannot read properties of undefined (reading someService)
The code in Compare is:
import {someService, somethingElse} from 'my-components';
. . .
someService.doSomething();
I saw the following warning during the build:
WARNING: { code: 'MISSING_GLOBAL_NAME', guess: 'myComponents', message: 'No name was provided for external module \'my-components\' in output.globals - guessing \'myComponents\'' }
So I explicitly added a global entry for it.
When I looked at the resulting code in the UMD module, the code looked like:
myComponents.someService.doSomething();
Why doesn't myComponents.someService resolve to the class that is exported from my-components?
My rollup.config.js looks like:
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.json'];
const umdGlobals = {
axios: 'axios',
lodash: '_',
react: 'React',
'react-dom': 'ReactDOM',
'my-components': 'myComponents'
};
export default [
{
input: 'src/components/index.js',
output: [
{ file: pkg.module, format: 'esm', sourcemap: true },
{ file: pkg.main, format: 'cjs', sourcemap: true },
{ file: pkg.umd, name: 'Compare', format: 'umd', sourcemap: true, globals: umdGlobals }
],
plugins: [
autoExternal(),
resolve({ extensions: EXTENSIONS, preferBuiltins: false, browser: true}),
commonjs({include: ['node_modules/**']),
babel({
babelHelpers: 'bundled',
babelrc: false,
presets: ['#babel/preset-env', '#babel/preset-react', '#babel/preset-typescript'],
plugins: ['#babel/plugin-transform-arrow-functions', '#babel/plugin-proposal-object-rest-spread', '#babel/plugin-proposal-class-properties],
extensions: EXTENSIONS,
exclude: 'node_modules/**'
}),
json(),
requireContext(),
internal(['classnames', 'pluralize'])
]
}
];
I tried to put my-components inside of internal(), and remove it from the global list, but that started to give other warnings that I think were the result of a dependency inside of it, and would throw errors when the bundle was used anyway.
Any advice on what I may be missing? Is there something wrong w/ the output from the my-components that I should be trying to fix in its rollup config, or is there something I can do in my rollup config for Compare?
Any help is greatly appreciated.

how to prevent multiple copies of React when developing library with Rollup?

I am developing tiny ui react library. I am using Rollup as a bundler. and i faced some strange issue:
react.development.js:1476 Uncaught Error: Invalid hook call. Hooks can only be called
inside of the body of a function component. This could happen for one of the
following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
Here is my Rollup config:
import babel from "rollup-plugin-babel";
import resolve from "#rollup/plugin-node-resolve";
import external from "rollup-plugin-peer-deps-external";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import typescript from "rollup-plugin-typescript2";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
const packageJson = require("./package.json");
export default [
{
input: ["./src/index.ts"],
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
globals: {
react: "React",
"react-dom": "ReactDOM",
},
external: ["react", "react-dom"],
plugins: [
peerDepsExternal({ includeDependencies: false }),
postcss({
plugins: [],
minimize: true,
}),
babel({
exclude: "node_modules/**",
presets: ["#babel/preset-react"],
}),
external(),
resolve(),
typescript({ useTsconfigDeclarationDir: true }),
terser(),
],
},
];
Component itself if very simple. Nothing special so i am skipping its code.
When i am publishing my lib to NPM - everything is working exactly as expected.
But when i am doing local instal with
npm i ../my-local-lib
I have this error in console:
react.development.js:1476 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
My expectation was that peerDepsExternal plugin will handle this case, but obviously i have messed up somewhere.

Using relative paths with react-native

I am trying to import Module using relative path in react-native , my project structure is like this :
-Project
--Components
--- adapter.js
--src
---screen
----Main.js
--App.js
I want to use adapter.js in my Main.js , so in the Main.js i use : import adapter from '/../Components/adapter'
this will throw the following error :
Module not found: Can't resolve '/../Components/adapter' in
'E:\reactjs\learn\Project\src\screens'
You can use https://github.com/tleunen/babel-plugin-module-resolver, it's a good module to have alias with import.
You have to specify a babel.config.js in React Native and a configuration:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./src'],
alias: {
components: './src/components',
_main: './src/components/_main',
screens: './src/screens',
config: './src/config',
navigations: './src/navigations',
utils: './src/utils',
actions: './src/state/actions',
constants: './src/state/constants',
contexts: './src/state/contexts',
reducers: './src/state/reducers',
assets: './src/assets/',
hooks: './src/hooks',
data: './src/data',
},
},
],
],
};
And after, you can import your module like this :
import HomeFeed from 'components/Home';
Note: that VSCode will detect the import
You need to add a tsconfig.js file
The next line
"baseUrl": "src"
Since your file Main.js is inside src/screen and adapter.js is inside Components, you need to go two levels down from Main.js to get out of screen, src and then enter Components.
You will end up with something like ../../Components/adapter.

Can't import npm modules in commonjs with rollup : "require is not defined"

I work on an ES6 project that I transpile using rollup and babel. It works well except when I try to import npm modules that use commonjs (and particularly require('something')) getting an error "require is not defined" in my browser (which means it hasn't properly compiled node modules from commonjs to ES5). However, I use rollup-plugin-node-resolve and rollup-plugin-commonjs, that should do that job if I've understood properly...
Here are my rollup config file:
import babel from 'rollup-plugin-babel';
import eslint from 'rollup-plugin-eslint';
import resolve from 'rollup-plugin-node-resolve'; // to import node_modules packages easily
import commonjs from 'rollup-plugin-commonjs'; // convert commonjs to es6 (in case you use require)
export default {
input: 'src/main.js',
output: {
file:'build/index.js',
format: 'iife'
},
sourcemap: 'inline',
plugins: [
resolve({
jsnext: true,
main: true,
browser: true
}),
commonjs({
include: 'src/**'
}),
eslint({
exclude: [
'src/styles/**',
]
}),
babel({
exclude: 'node_modules/**',
})
],
};
and my babel config file:
{
"presets": [
[
"es2015",
{
"modules": false
}
]
],
"plugins": ["external-helpers"]
}
Examples of modules that I can't load are math.js, nsolvejs, chroma.js, data.gui, etc.
The issue is probably with commonjs plugin, it is used to transform cjs into es modules at build time, therefore you should include the cjs modules from node_modules instead of src.
commonjs({
include: 'node_modules/**'
})

Rollup.js: undefined objects in external dependencies

I recently started playing with rollupjs. After configuring everything as per available docs and bundling things up, I got many errors from my external libraries about undefined objects. This sort of errors: Cannot read property 'parse' of undefined coming from crypto-js.
It complains about this line in the code: var ciphertext = Base64.parse(openSSLStr). So Base64 is undefined. I have few errors like this from different external libraries bundled in.
I use a handful of external dependencies:
chart.js,
crypto-js,
mithril,
moment,
pluralize
All of them work perfectly with jspm. I decided to try rollup to speed things up as jspm is soooo slow at the moment. Now half of my external dependencies stopped working. I get "undefined things" and "...not a function" kind of errors coming from external libraries only.
What could possibly be the cause of it?
This is my rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/scripts/application/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
uglify(),
],
dest: 'static/js/application.js',
};
Let me know if any other details are needed.
Thanks.
EDIT
I've done a simple tests-reproduction bundling those libraries that generate errors in my application.
package.json
{
"name": "minion",
"private": true,
"babel": {
"presets": [
"es2015-rollup"
]
},
"dependencies": {
"chart.js": "^1.0.2",
"crypto-js": "^3.1.6",
"mithril": "^0.2.2-rc.1",
"moment": "^2.11.1",
"pluralize": "^1.2.1"
},
"devDependencies": {
"babel-preset-es2015-rollup": "^1.1.1",
"rollup-plugin-babel": "^2.3.9",
"rollup-plugin-commonjs": "^2.2.0",
"rollup-plugin-npm": "^1.3.0",
"rollup-plugin-uglify": "^0.1.0"
}
}
rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
//uglify(),
],
dest: 'static/js/app.js',
}
main.js
import Application from './application'
import pluralize from 'pluralize'
var text = Application.run()
console.log(`Testing encryption: ${text}`)
console.log(`Testing pluralization: ${pluralize('person')}`)
application.js
import crypt from 'crypto-js'
var Application = {
run() {
var ciphertext = crypt.AES.encrypt('Testing encryption...', 'password')
var bytes = crypt.AES.decrypt(ciphertext.toString(), 'password')
return bytes.toString(crypt.enc.Utf8)
}
}
export default Application
Running the above will generate the errors.
Just speculating: Maybe is a bug of the rollup and/or crypto.
I have a similar error when trying to run a js function in Node Red, the js is ok when I run it locally but it throws TypeError: Cannot read property 'split' of undefined when runs remotely.
The only thing that my code have in common with yours is that both uses cryptography, specifically crypto-js 3.1.2 rollup "hmac-sha256.js" and the code is not imported but raw.
Even after deleting the only instance of 'split' yet I can't solve it (but keeps running locally)

Categories