Can react-loadable be used in create-react-app server-side? - reactjs

I am attempting to do some code-splitting in my create-react-app application that utilizes server side rendering.
I am utilizing 'react-loadable` to do the code-splitting: https://github.com/thejameskyle/react-loadable
As of now I simply have split my Home.js component away from the rest of my app, just to see if it works. In development mode (read: not SSR), it's chunked off and works fine.
However, I can't get things to work on the server. I'm following the guide on their Github page and am stuck because of the webpack changes needed. In create-react-app applications, you don't have access to webpack as it's hidden away.
The error I receive when starting the server is:
return (0, _importInspector.report)(import('../components/home/Home'), {
^^^^^^
SyntaxError: Unexpected token import
at createScript (vm.js:80:10) ...
I'm pretty sure it's because I don't have webpack configured correctly as stated in the guide.
In the guide, it clearly states for SSR:
First we need Webpack to tell us which bundles each module lives inside. For this there is the React Loadable Webpack plugin.
Import the ReactLoadablePlugin from react-loadable/webpack and include it in your webpack config. Pass it a filename for where to store the JSON data about our bundles.
// webpack.config.js
import { ReactLoadablePlugin } from 'react-loadable/webpack';
export default {
plugins: [
new ReactLoadablePlugin({
filename: './dist/react-loadable.json',
}),
],
};
I don't think this is possible without ejecting.
Anyone have any idea if react-loadable can be used in a create-react-app server-side-rendered application?

import these modules at the top of your server file
require('ignore-styles');
require('babel-polyfill')
require('babel-register')({
ignore: [ /(node_modules)/ ],
presets: ['es2015', 'react-app'],
plugins: [
'syntax-dynamic-import',
'dynamic-import-node',
'react-loadable/babel'
]
});

Related

Storybook webpack config not working - trying to run Storybook out of separate local project than components

I have a mature CRA-based React app running with Webpack 5. I would like to have a separate project (in git, etc) where Storybook lives and points to the components in the app. (The app has tons of devs in and out of it, and dropping a bunch of Storybook packages in there, as well as introducing legacy-peer-dependencies thanks to webpack 5, would be quite frowned upon).
I also want devs to have a good experience being able to use Storybook to write components, so I want Storybook to see the current code of the project components, not some exported package. And same as above, there are many devs and a lot of inertia, so moving components to a separate standalone library is not an option.
My ideal for local development:
components and stories: /MyProject-App/src/Components/...
storybook app. : /MyProject-Storybook/stories/...
(Production I'm not worried about yet)
Installing Storybook inside the app works fine (as long as you run with --legacy-peer-deps). I am using the npx storybook init script and it works fine. But if I try to run Storybook out of a separate directory and target the app directory's Components, it breaks. If I run Storybook out of the app, and point it to stories/components outside that repo (which I copied and pasted just as a debugging measure), it breaks. Going up and out of the current project root breaks.
To do this, I am trying to point stories in /MyProject-Storybook/.storybook/main.js to ../../MyProject-App/src/Components.... When I do this and npm run storybook, I get the error output:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
**You may need an additional loader to handle the result of these loaders.**
The error is always on some basic ES6 syntax, arrow functions etc. If I run the same Storybook install out of MyProject-App (same version numbers / same main.js just pointed at the local path instead of the ../other path) it works.
In addition to this, I tried it the other way - running storybook out of the App folder (where I know it runs), and only changing the main.js stories directory to an outside-that-repo folder where I copied my Components and stories into. It breaks in the same way - I get the same You may need an additional loader to handle the result of these loaders. message, with it pointing to any example of ES6 syntax as an 'error'.
I found this similar question - Storybook can't process TS files outside of the project
recommending to look into Storybook's webpack loaders - https://storybook.js.org/docs/react/builders/webpack
So I updated my .storybook/main.js to be the following:
module.exports = {
stories: [
'../../MyProject-Storybook/src/**/*.stories.mdx',
'../../MyProject-Storybook/src/**/*.stories.#(js|jsx|ts|tsx)'
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/addon-interactions',
'#storybook/preset-create-react-app'
],
framework: '#storybook/react',
core: {
builder: '#storybook/builder-webpack5'
},
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
reportFiles: ['../**/src/**/*.{js,jsx}', '../../MyProject-Storybook/**.stories.{js,jsx}']
}
}
]
});
config.resolve.extensions.push('.js', 'jsx');
return config;
}
};
but to no avail - output from npm run storybook remains unchanged, an excerpt:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
You may need an additional loader to handle the result of these loaders.
| backgroundColor: { control: 'color' },
| },
> } as ComponentMeta<typeof Button>;
|

rollup bundled react development resources

I'm using "vite": "^2.8.6" for React project. What I know is that Vite is using Rollup as module bundler, but I stumbled on a problem where Rollup still bundling my react-dom.development.js and react.development.js. I've used "rollup-plugin-replace" to replace my 'process.env.NODE_ENV' to production, but the problem still occur. Here is the my rollup config:
rollupOptions: {
// https://reactjs.org/docs/optimizing-performance.html#rollup
plugins: [
rollupPluginReplace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
rollupPluginCommonjs(),
terser(),
visualizer()
],
},
When I analyze with rollup-visualizer, you can see that rollup bundled both production and development dependency, which supposedly only bundled one of them right?
The problem with this is that there is extra 1MB of dead code in the bundle, it will be great if I can eliminate it.
This generally means that rollup does not understand that your app is directed towards production code. In my case it was because I had set up library mode.
lib: {
entry: './src/app.ts',
fileName: 'app.ts',
name: 'AppClass',
formats: ['iife'],
}
Removing this block finally generated a build which was sane in size. For more information, see the vite documentation.
If you were also trying to get vite/rollup to build your app as an IIFE, setting rollupOptions worked for me:
rollupOptions: {
output: {
entryFileNames: `[name].js`,
assetFileNames: `app.[ext]`,
format: 'iife',
},
input: ['./src/app.ts'],
},

Vite, NPM, React Component Library Invalid hook call, externals problem?

I was able to bundle my React Component library in Rollup, but I wanted the features of Vite for development and installed in over the weekend. My problem is that now I'm getting the following error when I try to npm link my vite generated distribution with another react probject.
Basically it's saying that it can't use useContext when it gets the 'Provider" which is really just a react context. It seems like it's having a problem here in the bundle when it tries to load it:
var Context=/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
My vite config looks as such:
export default defineConfig({
plugins: [react(), dts({ insertTypesEntry: true })],
build: {
lib: {
entry: path.resolve(__dirname, "src/lib/index.ts"),
name: "MyLib",
formats: ["umd", "es"],
fileName: (format) => `my-lib.${format}.js`,
},
rollupOptions: {
external: [ "react", "react-dom" ]
}
},
});
Searching said that it might be a problem with my dependencies, using two versions of react or react-dom. I've tried it with every dependency configuration I can think of and it all breaks in different ways. I think maybe npm cacheing could be confusing me or something though.
Have any ideas? Vite works fine in 'dev' mode, and the components were working ok in Rollup so I feel like it's just a dumb configuration thing I don't understand

How to import CSS file on Isomorphic React - Webpack

I'm trying to create an isomorphic react app using express, react, and webpack.
Everything works fine until I import a css file in one of my components. I understand node can not handle this import, but can someone explain how this package on github allows their components to have a css import line?
https://github.com/kriasoft/react-starter-kit
I would like to make my project similar to that. Do they have a line anywhere that has the server ignore that line when rendering components?
This is the error I get
SyntaxError: /home/USER/Code/shared/general/ru/src/components/MainPage/MainPage.scss: Unexpected token (1:1)
> 1 | #import '../variables.scss';
| ^
2 |
3 | .MainPage {
4 | background-color: $primary-color;
at Parser.pp.raise (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/parser/location.js:24:13)
at Parser.pp.unexpected (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/parser/util.js:82:8)
at Parser.pp.parseExprAtom (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/parser/expression.js:425:12)
at Parser.parseExprAtom (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/plugins/jsx/index.js:412:22)
at Parser.pp.parseExprSubscripts (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/parser/expression.js:236:19)
at Parser.pp.parseMaybeUnary (/home/USER/Code/shared/general/ru/node_modules/babylon/lib/parser/expression.js:217:19)
You need yet another loader to make css/style loaders to work.
https://www.npmjs.com/package/webpack-isomorphic-tools
But Webpack is made for client side code development only: it finds all require() calls inside your code and replaces them with various kinds of magic to make the things work. If you try to run the same source code outside of Webpack - for example, on a Node.js server - you'll get a ton of SyntaxErrors with Unexpected tokens. That's because on a Node.js server there's no Webpack require() magic happening and it simply tries to require() all the "assets" (styles, images, fonts, OpenGL shaders, etc) as if they were proper javascript-coded modules hence the error message.
Good luck!
Edit:
I think you also want to see this SO question. Importing CSS files in Isomorphic React Components
The project that the OP mentioned is using this:
https://github.com/kriasoft/isomorphic-style-loader
So yes, another loader + an interface to insert and use the styles.
Maybe you doesn't use the sass loader in tour webpack configuration.
Try install this loader:
Sass loader
Example of webpack config:
module.exports = {
...
module: {
loaders: [
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
}
]
}
sassLoader: {
includePaths: [path.resolve(__dirname, "./some-folder")]
}
};
I can suggest also you to use postcss to apply autoprefixer!

React webpack undefined react in console

I have problem with webpack build I write custom webpack config:
https://github.com/Simproduction/react-client-webpack
but when I run dev or build a project everything work correct but I can't call React from console or use react developers tools
I get error
Uncaught ReferenceError: React is not defined(…)
Could you help me?
My test project,
https://github.com/Simproduction/react-CM
You need to expose React so it is available on the window using the expose-loader:
module: {
loaders: [
{ test: require.resolve("react"), loader: "expose?React" },
]
}
It contains AMD and CommonJS in webpack. You know js loader, right?
If you use AMD ,you know that all js code are in 'define([],function(){ var a=10; ...}) area. if you want print a in console. You should like this
define([],function(){
var a=10;
window.a = a;
})
so, you can edit your main.js. Add this line window.React = React; , but we may use CDN instead of it is common solution.

Resources