Bug description
I am working with a library called react-carousel from brainhubeu in NextJS. Even when I am using dynamic import with ssr:false, The build UI looks strange but the dev UI is perfectly fine.
dev UI -
I have recreated it in Codesandbox too (this one is for dev environment is running npm run dev)-
https://codesandbox.io/embed/suspicious-volhard-460q8?fontsize=14&hidenavigation=1&theme=dark
However when I build it and then run the build by using npm run build && npm run start -
To recreate this in codesandbox -
In bottom right click on + sign for a new terminal
npm run build
npm run start (I have already added "start": "next start -p 8080" in the package.json file so a new tab will be created for the sandbox and can be accessed as https://460q8-8080.sse.codesandbox.io/ where 8080 signifies the port number )
Expected behavior
UI should be same as when seen with npm run dev.
Question
Why does my dev UI works fine but when I build and serve, the UI is strange. What exactly is the difference between npm run dev and npm run build && npm run start in context of NextJS?
Any solution to this problem?
My attempts
I have been trying to work on this problem and have asked this question on official Github discussions on NextJS. Couldnt find any answer.
I even created a Github Bug issue on react-carousel's Github, they couldn't help much.
Thanks for helping out.
I was able to resolve this issue. In my case, it was due to the difference between how I had set up (dev) and next build && next start. Take note of a few things to get it sorted -
If you have used an external library, chances are it doesn't support server-side rendering. I was using react-carousel from Brainhubeu and it having some issues. Resolve it by importing the library via next/dynamic imports with ssr:false option.
Another issue was that I was using/following an outdated boilerplate code for Tailwind and NextJS. Hence the way postcss.config.js was configured was error-prone. Here is the crux of the problem. at least for me - During the dev, everything worked fine because postcss didn't purge any of the classes of third party plugins/libraries that I imported, however, they were being purged when I did npm run build and npm run start
Now let's quickly see how you can solve this issue on your part -
Use the inbuilt purge option provided by TailwindCSS. For this, use the official starter-code/boilerplate code from the NextJS team. As they mention there - To control the generated stylesheet's filesize, this example uses Tailwind CSS' purge option to remove unused CSS.
Or you could try patching the problem if you don't want to go the previous way. I would only suggest this method if you are almost done with the project and just want to get this working because this is in no way a good solution. You will have to whitelist a bunch of css files from being purged. This is what I did but you can probably whitelist a lost more CSS classes as well -
// postcss.config.js
const purgecss = [
"#fullhuman/postcss-purgecss",
{
content: [
"./node_modules/#brainhubeu/react-carousel/lib/style.css",
"./node_modules/#brainhubeu/react-carousel/lib/style.css.map",
"./node_modules/react-toastify/dist/*.css",
"./components/**/*.js",
"./pages/**/*.js",
],
defaultExtractor: (content) => {
const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [];
const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || [];
return broadMatches.concat(innerMatches);
},
},
];
module.exports = {
plugins: [
"postcss-import",
"tailwindcss",
"autoprefixer",
...(process.env.NODE_ENV === "production" ? [purgecss] : []),
],
};
Still I would suggest go the first way and copy your code from old repo to new, use SSR:false to use client-side libraries that hate SSR, and you should be good to go.
You can reach out to my Twitter #toughyear if you need help with this.
Related
I have a Vite/React/Typescript/Yarn monorepo that contains two applications and some shared components. I'm having trouble getting HMR working when running vite dev.
The example repo is here: https://github.com/jakeboone02/em-hmr-test. If you run yarn && yarn start:app1, open http://localhost:3012/, then edit any of the components and save, the page will reload instead of just replacing the component in place.
The repo is a stripped down version of the actual proprietary code. I tried converting all the exports to defaults as suggested in this discussion question answer, but the page still reloads on every change.
Is there something wrong with the Vite config that is preventing HMR from working?
Turns out I was using the deprecated #vitejs/plugin-react-refresh instead of the newer, shinier #vitejs/plugin-react. Repo has been updated.
I am facing an issue with code highlighting when using prism-react-renderer component in Gatsby. I have configured it as per instructions in FormidableLabs/prism-react-renderer.
Everything works in development mode, but when I build a production version with the gatsby build command, the pre tag is not decorated with prism classes (class="prism-code language-python" is missing). My guess is that the production build does not include the right component or CSS, but I don't know where to start looking.
Also, this issue was not present when I used the same code 7-8 months back in another project. So it may be a problem introduced in the past few months because of a plugin/component update.
Attached are two screenshots - one with gatsby develop and another with gatsby build.
Commands I ran to setup and install the requisites:
> gatsby new test-mdx-prism-rendering https://github.com/gatsbyjs/gatsby-starter-hello-world
> npm install --save gatsby-plugin-mdx #mdx-js/mdx #mdx-js/react
> npm install --save mdx-utils
> npm install --save prism-react-renderer
Sample GitHub project is at subhashb/test-mdx-prism-rendering
Found the answer as I tried to dig deeper.
The workaround is discussed here: https://github.com/ChristopherBiscardi/gatsby-mdx/issues/394
Apparently, the wrapRootElement defined in gatsby-browser.js should be made available in gatsby-ssr.js as well.
I have an npm package (that I published) which causes duplicate React instances and hence the following Component Exception:
"Invalid hook call. Hooks can only be called inside of the body of a function component..."
What should I do in order to prevent this error from occurring in projects that download this package?
EDIT: The following answer relates to publishing a package and not installing.
For future generations (and current) in case you came across with the same issue, meaning that you ran npm ls react and saw 2 different instances of React. The problem is due to the fact that React should be in your package.json under the peerDependencied and not under dependencies.
You can find a lot of info about it online but I recommend reading this article as it simplifies the subject and makes it clear.
Within a single app, React may exist in several instances (the most probable reason):**
If you use Node for package management, you can run to check the React duplicity in your project folder:
npm ls react
to slove the issue : 1. don't use react , react-dom as dependencies or devDepenencies in your published package's package.json file, rather just mention them as peerDependencies
2.(how usually I solve this issue): mention inside the webpack.config.js file :
resolve: {
alias: {
react: path.resolve("./node_modules/react"),
},
},
Simple, when you create your package, dont specify any version to react
in dependency add "react:": "*"
This will mean that it will use whatever react version that are installed on the user project
I have set up a project using ionic framework v4 with React and wish to add a webpack loader to allow importing graphql queries from .graphql files, as described here.
I can't find any official documentation on how to change anything relating to webpack (for example, nothing here), and existing answers on the subject seem to apply only to using Angular or v2/v3 of ionic.
The Apollo docs describe an alternative way of solving this for Create-React-App (which I may try as a workaround), but I might wish to change webpack config in other ways, so I am also asking how to solve this question more generally.
You can customize webpack using react-app-rewired
If you don't use ionic cli to build and run your app, you can use a normal install of react-app-rewired.
If you use the ionic cli, there is an additional step/trick:
Ionic uses react-scripts under the hood, so you need to trick it into using react-app-rewired instead of react-scripts.
Here is a simple and low-invasive way to have Ionic cli use react-app-rewired instead of react-scripts: add this package.json postinstall script:
{
"scripts": {
"postinstall": "cd node_modules/.bin && mv react-scripts react-scripts-real && ln -s ../react-app-rewired/bin/index.js react-scripts",
...
}
}
Update: This fails when you run ionic build because it defaults back to using react-scripts build.
Not sure why I didn't see this before, but taking a closer look at the bootstrapped ionic project, it’s clearly using create-react-app/react-scripts.
Although CRA demands you do a one-time eject in order to configure anything relating to the build, I was able to use react-app-rewired and customizable-cra to customise the build and start scripts. As far as I can tell this works fine with ionic.
I'm trying to get i18n message extracted (defined by react-intl's defineMessages) to work properly in a CRA using TypeScript.
I've got an existing react app bootstrapped by CRA with a couple of hundrets of lines of code. So rewriting the application w/o TypeScript isn't an option.
Here's what i've tried so far:
First Attempt
Following this guide in order to get it to work.
When closely following the guide (although react-intl-cra is deprecated) the language files will generate properly.
However if you create the app using create-react-app react-intl-example --typescript and change the script to
"extract:messages": "react-intl-cra 'src/**/*.{js,jsx,ts,tsx}' -o 'src/i18n/messages/messages.json'"
it will break with a compiler error.
Second Attempt
Since react-intl-cra was refering to a react-app-rewired solution, I've tried adding it alongside customize-cra and babel-plugin-react-intl to a freshly generated CRA (using TS). However no luck there as well and after some short period of research I found that it's officially not supported.
Third attempt:
Adding extract-react-intl-messages to my project and running:
$ npx extract-messages -l=en,ja -o app/translations -d en --flat false 'src/**/!(*.test).tsx'
failed with an error as well.
I ran out of ideas, hence I came here to ask. From what I've seen TypeScript has been well advertised in the last couple of years and I don't think I have to justify that React is still pretty hyped. Moreover I can't imagine, that i18n is an uncommon concern in application development.
However I wasn't able to find any up-to-date guide or anything useful on npmjs.com.
TL;DR;
What I need:
Extract messages from defineMessages from react-intl into json files
Must work in a CRA using --typescript
Should not utilize npm run eject
What I've tried:
react-intl-cra
react-app-rewired + customize-cra + babel-plugin-react-intl
extract-react-intl-messages
It's explained here: https://github.com/akameco/extract-react-intl-messages#typescript
Basically you need to
npm install --save-dev #babel/core #babel/preset-typescript #babel/preset-react
and add
#babel/preset-typescript
to your .babelrc:
{
"presets": [
"#babel/preset-react",
"#babel/preset-typescript"
],
}
Then you can run
npm run extract-messages 'src/**/*.[jt]sx'