<FullCalendar
initialView="timeGridWeek"
allDaySlot={false}
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin]}
locale={deLocale}
/>
./node_modules/@fullcalendar/core/main.css
Global CSS cannot be imported from within node_modules.
Read more: https://err.sh/next.js/css-npm
Location: node_modules/@fullcalendar/core/main.js
I think the issue sits here https://github.com/fullcalendar/fullcalendar/blob/d3a2b13db43cfe9a450091776da3be25a0ca15c0/packages/common/src/main.ts#L1.
I recommend to not require styles in the core. It should be included by the package consumer.
More info https://github.com/zeit/next.js/blob/master/errors/css-npm.md
having FC import its own CSS files via the JS is pretty core to how FC works (in v5 at least). it's better than having to manually cobble together CSS from the different plugins.
for your case, I'd recommend using the fullcalendar bundle instead, which does NOT import its own CSS. the v5 fullcalendar bundle can be installed with npm install [email protected]
and then you'll somehow need to include the CSS file in node_modules/fullcalendar/main.css
i plan on writing more docs about this
I see that as bad practice when a library which is fully customizable via CSS enforce the consumer side to proceed other files than js. Just document how to include the default theme. This reduce size and increase flexibility.
Please read this blog post to learn my rationale behind choosing this design: https://fullcalendar.io/blog/2020/02/changes-in-the-upcoming-v5#packaging-and-distribution
tldr: there is no single "default theme" but rather a network of interdependent CSS files
For people who don't want to deal w/ this, just simply use the bundle like I recommended to you.
but i see you're using React, which the bundle won't work for. Lemme think more about this.
note to self: custom webpack config - https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config
The win here is that you’ll no longer need to import each package’s CSS file manually. This is especially important for packages like @fullcalendar/timegrid which depends on @fullcalendar/daygrid, whose CSS file needs to be included as well. You won’t be forced to understand the dependency graph to know which CSS files to include.
I read your article and I'm still not convinced. I see it more than a disadvantage because it produces incompatibilities. The described issues can be easily fixed with proper documentation.
note to self: custom webpack config - nextjs.org/docs/api-reference/next.config.js/custom-webpack-config
Next.js already supports css and sass imports but it refuses to import global CSS/SASS files in modules other than in the app root component because the import order can't be guaranteed. The design decision will make your module incompatible with Next.js a very popular react framework.
Hey @StarpTech, the way you want things to work is the way they currently work in v4. It's pretty well documented on the pages for the various views (like timeline view) and people still had trouble. They'd forget one of the necessary stylesheets and write into github or our support email with a busted-looking calendar. That's the whole reason I'm changing this. It's a response to past confusion.
It'd be a different situation if there was a single .css file for every package, with no interdependencies. However, sometimes the dependency graph is not obvious. Resource-timeline view requires stylesheets from the core and timeline modules as well. And v5 will make it worse because there are more intermediate dependencies. In v5, resource-timeline view will need core, timeline, scrollgrid AND datagrid. It's a lot to ask a developer to include 4 additional arbitrary stylesheets!
In v5, having a build system handle the importing of the CSS has been well received so far. Anyone using a build system is able to easily configure it to do this. I never imagined there'd exist a build system that makes it difficult to do this, but alas we have Next.js. This is the only environment I'm aware of where it's difficult. Nonetheless, I'd like to come up with a workaround to help Next.js users.
Have you looked at next-transpile-modules? It looks like it tricks Next into processing CSS.
I don't understand why Next.js refuses to import CSS. Why can't the import order be guaranteed? If it's guaranteed in your main app, I don't understand why it can't be guaranteed in the app's dependencies. It should output in depth-first traversal order just like Webpack would naturally do. Or am I not understanding something about Next.js? And Next.js should just put it in the global scope by default.
I don't understand why Next.js refuses to import CSS. Why can't the import order be guaranteed? If it's guaranteed in your main app, I don't understand why it can't be guaranteed in the app's dependencies.
It does not refuse it all it only allows global css to be imported at a central place. The reasons aren't that easy see https://github.com/zeit/next.js/issues/8626
Here you can find more information about the error https://err.sh/next.js/css-npm
I'm looking forward to the new release and I hope you will find a good solution.
Hey @StarpTech, the way you want things to work is the way they currently work in v4. It's pretty well documented on the pages for the various views (like timeline view) and people still had trouble. They'd forget one of the necessary stylesheets and write into github or our support email with a busted-looking calendar. That's the whole reason I'm changing this. It's a response to past confusion.
I think they just didnt read your docs ☺
or they have no clue what they actually doing. This is a complete different issue. I would not compensate it with the current design.
Have you looked at next-transpile-modules? It looks like it tricks Next into processing CSS.
That are hacks and I don't want to use them because the reasons behind the limitation are reasonable.
I'm installing fullcalendar for the first time for my Next.js app and this issue is a blocker.
Have you looked at next-transpile-modules? It looks like it tricks Next into processing CSS.
This is not enough, because Next.js still forbids global CSS imports:
./node_modules/@fullcalendar/common/main.css
Global CSS cannot be imported from files other than your CustomRead more: https://err.sh/next.js/css-global
Location: node_modules/@fullcalendar/common/main.js
Seems like I'm stuck with v4 until this issue is resolved.
Hi @berekuk I read the code of next-transpile-modules and it should solve all issues even if I don't like to work around the default Next.js webpack configuration because it could break at any time :smile:
@berekuk, https://github.com/martpie/next-transpile-modules
It also supports global CSS import packages located in node_modules:
// pages/_app.js import 'shared-ui/styles/global.css'; // will be imported globally export default function MyApp({ Component, pageProps }) { return <Component {...pageProps} />; }
@arshaw this is possible by default because you require it in _app.js
hmm, in that case the example on the next-transpile-modules readme doesn't seem to make sense. the title of the code example says "It also supports global CSS import packages located in node_modules", but then the code has nothing to do with node_modules.
anyway, did you get it to work personally @StarpTech ?
@arshaw I think he means that you are able to include from node_modules everywhere.
anyway, did you get it to work personally @StarpTech ?
Did you change something? I didn't spend more time on it.
Anybody had any luck with this? I've taken a look to next-transpile-modules but like @arshaw says it has nothing to do with node_modules; it's really a shame it does not work out-of-the-box with Next since V5 seems to solve all the issues we had with V4.
I have the same problem. I can't upgrade to v5.0 because Next.js can't import global CSS from within node_modules.
@arshaw
This is RFC regarding Next.js Built-in CSS Support. Here's why we shouldn't load Global CSS from within node_modules.
https://github.com/vercel/next.js/issues/8626
Both FullCalendar and Next.js are great software, so I hope this issue is resolved.
Here's my workaround for this. It's ugly and it'll probably break on future Next.js upgrades, but it works.
// next.config.js
module.exports = {
webpack: (config, options) => {
const nextCssLoaders = config.module.rules.find(
rule => typeof rule.oneOf === 'object'
);
nextCssLoaders.oneOf.forEach(loader => {
if (
loader.sideEffects &&
loader.issuer &&
loader.issuer.include &&
loader.issuer.include.endsWith('_app.tsx')
) {
delete loader.issuer;
}
});
return config;
},
};
(I had to dig into next-transpile-modules and Next.js code to figure it out.)
Also, I learned that Next.js is more right about their stance "CSS order is unpredictable, so we'll forbid imports outside of pages/_app" than I expected. In my case, CSS applied differently in dev and in production, and I had to patch my styled-components wrapper with CSS overrides to fix some related issues which didn't reveal themselves in dev.
@berekuk Yes you're right, we have had some problems with CSS being applying different in production than in dev. Anyways thanks for the workaround! Hope the Fullcalendar team offers a less hacky way to support Next.
Any update on this @arshaw? It would be nice to use V5 in next without these complications.
How important is it to people to import individual fullcalendar packages, as opposed to a whole bundle, in order to save space? The best solution I can think of right now is to import newly exposed ES module from either the fullcalendar package or fullcalendar-scheduler package:
import fcPlugins from 'fullcalendar/plugins';
import 'fullcalendar/main.css';
// then, in the JSX...
<FullCalendar
initialView="timeGridWeek"
plugins={fcPlugins}
/>
How important is it to people to import individual fullcalendar packages, as opposed to a whole bundle, in order to save space? The best solution I can think of right now is to import newly exposed ES module from either the
fullcalendarpackage orfullcalendar-schedulerpackage:import fcPlugins from 'fullcalendar/plugins'; import 'fullcalendar/main.css'; // then, in the JSX... <FullCalendar initialView="timeGridWeek" plugins={fcPlugins} />
In direct answer to your question, utilizing a complete package does not present a space/performance issue here. And I for one appreciate your frustration with people not reading the docs, and therefore understanding the dependency tree. Few could argue re: ease of use utilizing the packages FC v5 provides. Excepting of course, people such as Next.js users.
"For people who don't want to deal w/ this, just simply use the bundle like I recommended to you." It just not that simple. And not just for Next.js users, who appear to be rather like the canaries in our coal mine.
The problem with Next.js integration isn't the only (practical) issue re: these packages. For example, the exclusion of the rrule plugin from the available packages illustrates a problem for users in some environments (CMS systems, etc.). v4 brought along rrule support; a giant leap forward. v5 has now has effectively been eliminated from environments that utilize that plugin but cannot/do not use a package manager. My apologies to Next.js users with the problem described; this must seem OT.
tldr: Like most things; packages are great until they are not. With the rrule.js plugin as an example, even those users that can make use of a package manager will need to understand the tree with regard to how to build their package.
@21Junipers, thanks for the input. I'm aware of the issue with the rrule plugin and I'll come up with a solution for that.
Question for all: I have some ideas on how to better solve these issues between Next.js and FullCalendar v5, and I want to play around with a runnable setup, but I can't get to the point where I see the Global CSS cannot be imported from within node_modules error. I'm getting stuck with a different error: Cannot use import statement outside modules. Are you all using babel to somehow transpile FullCalendar's JS files from ESM->CJS?
If so, could someone generously post a Codesandbox demo? I would really appreciate it. I'm spending too much time with boilerplate and not enough time on the meat of the problem.
@arshaw Here you go: https://codesandbox.io/s/upbeat-tdd-d54q1?file=/pages/index.tsx
The dynamic part is just to tell Next not to server-side render Fullcalendar, otherwise throws a "window is not defined" error.
Thanks @alessandrojcm, that is really helpful!!! I see you are using next-transpile-modules to transpile from ESM->CJS.
@StarpTech, question for you. You said that you are NOT using next-transpile-modules, but you're still somehow getting to the the point where you see the Global CSS cannot be imported from within node_modules error, which means you're somehow transpiling FC's provided ES modules. How are you doing this? Are you using babel to do this?
You said that you are NOT using next-transpile-modules, but you're still somehow getting to the the point where you see the Global CSS cannot be imported from within node_modules error, which means you're somehow transpiling FC's provided ES modules. How are you doing this? Are you using babel to do this?
Not sure, if I understood your question correctly but I just import FC in Next.js
I feel like I need to clarify, @arshaw: next-transpile-modules is something I added specifically to that codesandbox in order to get to the specific CSS error.
In our project, we only get the Global CSS cannot be imported from within node_modules error sporadically; when that happens I just tend to refresh the page and it works again. I couldn't pin down a specific behavior to reproduce this, only that it usually happens after the app hot reloads (like I said, sometimes it happens sometimes it doesn't).
We don't have any specific Babel configuration; in fact we don't have any, we just use Next's defaults which you can check here. And our next.config.js looks like this:
const path = require('path');
const webpack = require('webpack');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
let environment = 'development';
if (process.env.NODE_ENV) {
environment = process.env.NODE_ENV;
}
const { parsed: localEnv } = require('dotenv').config({ path: path.resolve(__dirname, `./src/environments/${environment}.env`) });
const nextConfig = {
webpack(config) {
config.plugins.push(new webpack.EnvironmentPlugin(localEnv));
config.optimization.minimizer = [];
config.optimization.minimizer.push(new OptimizeCSSAssetsPlugin({}));
const nextCssLoaders = config.module.rules.find((rule) => typeof rule.oneOf === 'object');
nextCssLoaders.oneOf.forEach((loader) => {
if (loader.sideEffects && loader.issuer && loader.issuer.include && loader.issuer.include.endsWith('_app.tsx')) {
delete loader.issuer;
}
});
return config;
},
};
module.exports = {
...nextConfig,
};
Nothing fancy, just the workaround @berekuk suggested in order to get Fullcalendar working.
This all makes sense. FullCalendar is published as ES modules, and next-transpile-modules did the converting from ESM->CJS. That being said, next-transpile-modules does NOT go as far as to compile the imported CSS file, thus the error, and thus the need for the crazy webpack workaround.
@StarpTech I bet you never encountered the need to transpile from ESM->CJS because you ran into the problem while using one of the v5 beta versions, which was compiled CJS.
ANYWAY, I'm pretty sure I've come up with a solution that will satisfy all. I'll publish BOTH an ESM and a CJS. Each of FullCalendar's packages' package.json will look like this:
"module": "main.esm.js", <-- for Webpack, Parcel, Rollup. will import main.css
"main": "main.cjs.js", <-- for Next and others. will NOT import main.css
The straightforward JS loaders like Webpack, Parcel, and Rollup will know to use the ESM because they are configured by default to look for the non-standard module entry. All other environments will look for main. Luckily Next.js, and Nuxt, and Jest ... all the environments that were choking while importing a CSS file ... all use main by default.
The crux of this solution is that the ESM will import the CSS file whereas the CJS will not. I know it's a little weird to make two different module formats that have slightly different execution behavior, but another way to think about it is that the main.cjs.js is a gracefully-degraded version of main.esm.js that does not know how to import CSS.
Does this sound like a good solution to people?
A followup question: in the CJS file that Next consumes, would you like me to embed the styles via a dynamically-injected <style> tag? This would alleviate the need to import all of FullCalendar's CSS files manually. The downside is that you couldn't use PostCSS to customize FullCalendar's CSS variables nor do any other PostCSS transformations.
The crux of this solution is that the ESM will import the CSS file whereas the CJS will not. I know it's a little weird to make two different module formats that have slightly different execution behavior, but another way to think about it is that the main.cjs.js is a gracefully-degraded version of main.esm.js that does not know how to import CSS.
Importing css is in general just a feature by the bundler. The user should not be forced by doing this at all. As a Next.js user, I'd like to import the required CSS/SASS in the root application.
@StarpTech, yes, I know, you've made that point very clear, and the solution I'm proposing will allow you to do exactly that. I can't tell whether you're agreeing with me or disagreeing with me.
"module": "main.esm.js", <-- for Webpack, Parcel, Rollup. will import main.css "main": "main.cjs.js", <-- for Next and others. will NOT import main.cssDoes this sound like a good solution to people?
Good enough for us!
A followup question: in the CJS file that Next consumes, would you like me to embed the styles via a dynamically-injected
<style>tag? This would alleviate the need to import all of FullCalendar's CSS files manually. The downside is that you couldn't use PostCSS to customize FullCalendar's CSS variables nor do any other PostCSS transformations.
I'd prefer to import the CSS styles manually, feels more standard to me.
@arshaw While you're at it could you consider fixing the issue that requires next developers to dynamically import the calendar? The problem is when server side rendering there isn't a reference to document or window and apparently there is a call made to window at some point in the calendar while server side rendering. It could be as simple as a check like if typeof window !== 'object' don't use window. Although this process may be whatever is manipulating the calendar to make it render the way it does. Preferably the calendar's skeleton should be able to render server side without making any calls to window or document. Then once it is client side rendered do whatever calls to window as necessary.
@arshaw I appreciate all your work on this trying to strike the right balance. I came across this error while consuming FullCalendar from ClojureScript, which definitely appears to fall under the and others umbrella. :smile:
My specific issue is with the interaction plugin, when doing the equivalent of import interactionPlugin from "@fullcalendar/interaction", which depends (through common/main.js) on common/main.css. It's choking on that because the ClojureScript compiler doesn't know anything about CSS. If I'm understanding your proposed solution correctly, I think it will solve my problem too. What I'm wondering is what that looks like beyond updating each package.json? How will the main ESM/CJS files get there in the first place? Is it a bunch of changes across packages, or more akin to a few lines in a webpack/rollup config?
Asking because this is a blocker for me right now and my only recourse seems to be to fork FullCalendar and remove the CSS import. So if I'm going to go through that effort, I may as well try and help fix it for everyone.
As for your followup question, I definitely would err on the side of flexibility over convenience, and not include the inline styles.
@acobster, I need to make each package output a CJS module in addition to the ESM it's already outputting. It will require quite a bit more configuration in the rollup config that is run when FullCalendar is built. BTW, I'll also be needing to add more config for a JS global dist file as well.
It sounds like the solution described in this ticket will help your situation as well.
I plan to release this in about 2 weeks, but might take a bit longer. Maybe simply removing the .css import will be a good workaround in the meantime. Though if you could somehow convince the ClosureScript transpiler to ignore .css imports, that'd be the ideal workaround for now.
Sounds like you have a pretty good handle on it then. That's a pretty hefty rollup config so I'm not sure how helpful I'd be anyway. :) Apparently the ClojureScript compiler I'm using (shadow-cljs) already supports an :ignore-asset-requires config option. So I'm past the error now. Thanks!
Found a fix...thought I'd share.
Break your calendar out into its own component and dynamically load it. Works perfect.
import dynamic from 'next/dynamic';
const CalendarPage = dynamic(
() => import('../../components/CalendarPage'),
{
ssr: false,
loading: () => <p>...</p>,
}
);
And, in CalendarPage:
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
It turns out my proposed solution won't work because Next actually uses the module field when it's available.
FullCalendar v5 must still continue to distribute its CSS in the current way because A) developers in other environments enjoy this behavior and B) I can't introduce a breaking change until v6, so...
Users of Next.js will need to explicitly exclude FullCalendar's CSS files from inclusion. And then they must include the stylesheets manually. I've written an examples of the best way to do this using a Babel transform (see below).
Separately, Next.js doesn't process third-party ES modules and you must trick it into doing this using next-transpile-modules. I've written an example (see below).
Fixing SSR was the final hurdle in getting FullCalendar to work with Next.js (cc @c27cochran). I've fixed all SSR issues in v5.2.0
EXAMPLE PROJECT: (the newly released v5.2.0 is required)
https://github.com/fullcalendar/fullcalendar-example-projects/tree/master/next#workarounds-explained
A Cleaner Solution in the Future
When the features mentioned above are implemented, no more hacks will be required to get FullCalendar working with Next. In my opinion, Next is an overly restrictive environment for third-party packages that is not keeping up to date with the latest JS ecosystem developments, creating headaches for package authors like myself. I've spent an inordinate amount of time addressing Next incompatibilities, more than I have with any other framework or environment. Even Nuxt (the Vue-based cousin of Next) more-or-less works out of the box.
I'm closing this issue because I've provided semi-satisfactory workaround, which I've included in FullCalendar's documentation.
having FC import its own CSS files via the JS is pretty core to how FC works (in v5 at least). it's better than having to manually cobble together CSS from the different plugins.
for your case, I'd recommend using the
fullcalendarbundle instead, which does NOT import its own CSS. the v5 fullcalendar bundle can be installed withnpm install [email protected]
@arshaw Sorry for adding a comment in a closed issue.
In my company, we prefer styled-components over global CSS files.
I see you mentioned this bundle that doesn't import CSS automatically but it is in beta.
Is there an official v5 bundle that doesn't import CSS?
Ideally, we'd prefer using a bundle like that than changing the wepack configuration to prevent the CSS from being loaded.
@leogdiniz read my last comment: https://github.com/fullcalendar/fullcalendar/issues/5393#issuecomment-667701320
Most helpful comment
@berekuk Yes you're right, we have had some problems with CSS being applying different in production than in dev. Anyways thanks for the workaround! Hope the Fullcalendar team offers a less hacky way to support Next.