typescript project like App.jsx can not code split with @loadable/babel-plugin.
I'm forked this project and copied examples/server-side-rendering-ts.
Example js code was transformed to ts or tsx.
After yarn build:webpack, there is only one js file main.js in public/dist/node and public/dist/web. It seems like @loadable/component not working properly.
If yarn start, you can see an error "Invariant Violation: loadable: SSR requires @loadable/babel-plugin, please install it"
Output of yarn build:webpack is letters-A.js, letters-B.js, letters-C.js.... etc and main.js like server-side-rendering.
For typescript project, I changed some config
src to ts-output because babel can not read typescript directly.ts-output is compiled files from src. I guess my problem is 'Loadable detection'.
Seeing ts-output/client/App.js in here
(https://github.com/DylanJu/loadable-components/tree/master/examples/server-side-rendering-ts/ts-output/client)
App.tsx
const A = loadable(() => import('./letters/A'))
compiled App.js
const A = component_1.default(() => Promise.resolve().then(() => __importStar(require('./letters/A'))));
It seems keyword loadable is gone. So @ladable/babel-plugin can not detect code splitting. It's just my opinion.
Please help me!
Hello @DylanJu, I am not Typescript compliant. @theKashey help!
@neoziro @theKashey
It is solved by myself. The problem is because typescript compile as I guessed.
Using webpack, babel and typescript same time, A.tsx is compiled in order ts-loader, babel-loader, webpack.
In my case, ts-loader changed loadable based on typescript config.
If configure tsconfig.json like this
"compilerOptions": {
"module": "commonjs",
}
It change App.tsx
const A = loadable(() => import('./letters/A'))
to
const A = component_1.default(() => Promise.resolve().then(() => __importStar(require('./letters/A'))));
Then @loadable/babel-plugin can't detect loadable
tsconfig.json
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
}
It don't change loadable(() => import('something') so the detection is enable compile normally.
I wish help someone like me.
And I think it's needed a guide to this for someone who use typescript.
I would suggest (having babel coming next):
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"jsx": "preserve", // <--- this is important
"target": "es2016" or "esnext" // <-- this might be important for arrow functions
}
@theKashey
Thanks your suggest.
I'm using "target": "esnext", "jsx": "react", it's not make any problem but I'll follow your suggest.
Thanks again.
I'm ok this issue can be closed.
but I hope that the official README show your suggest for typescript user.
@DylanJu I have the same issue when converting to TypeScript (The system works ok with normal JS).
The compiled files now are named as 0.js, 1.js, etc., instead of A.js, B.js, where A and B are the name of loadable components.
My tsconfig.json:
{
"compilerOptions": {
"outDir": "./dist/",
"esModuleInterop": true,
"sourceMap": true,
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "node",
"target": "esnext",
"jsx": "react"
}
}
and here is the webpack config:
module.exports = {
entry: './client/index.tsx',
output: {
path: path.join(__dirname, 'dist'),
// filename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: 'ts-loader',
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
...
}
Can you help me?
Never mind. The order of loaders are important.
I changed the loaders to
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: ['babel-loader', 'ts-loader'], // The orders are important
},
and it works perfectly now!
@phuoc-ng what are your configs for ts and babel? Could you share these plz?
@dakiesse Yes, sure.
I have been using loadable-components for a few sites such as this vs that, CSS Layout, HTML DOM with the same setup as following.
All those sites are open source, so you can take a look at them or fork one of them.
Here is an example
"dependencies": {
"@loadable/component": "^5.12.0",
},
"devDependencies": {
"@loadable/babel-plugin": "^5.12.0",
"@types/loadable__component": "^5.10.0",
"babel-loader": "^8.0.6",
"ts-loader": "^6.2.1",
}
{
"plugins": ["@loadable/babel-plugin"],
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
module.exports = {
...
module: {
rules: [
...
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
// The order of loaders are very important
// It will make the @loadable/component work
use: ['babel-loader', 'ts-loader'],
},
...
],
},
...
};
const App = () => {
return (
<Router>
<RouteSwitch>
<Route
path='/:slug'
render={(props) => <PostLoader slug={props.match.params.slug as string} />}
/>
</RouteSwitch>
</Router>
);
};
PostLoader.tsx will use @loadable/component to load a page located in the ../posts folder:
import loadable, { LoadableComponent } from '@loadable/component';
import React from 'react';
import Spinner from './Spinner';
interface PostLoaderProps {
slug: string;
}
const loadDetails = /* #__LOADABLE__ */ (props: PostLoaderProps) => import(`../posts/${props.slug}`);
const PostLoader: LoadableComponent<PostLoaderProps> = loadable(loadDetails, {
fallback: <Spinner />,
});
export default PostLoader;
I hope it helps you.
Thanks, @phuoc-ng, worked for me.
Most helpful comment
@neoziro @theKashey
It is solved by myself. The problem is because typescript compile as I guessed.
Using webpack, babel and typescript same time,
A.tsxis compiled in orderts-loader,babel-loader,webpack.In my case, ts-loader changed
loadablebased on typescript config.If configure tsconfig.json like this
It change App.tsx
const A = loadable(() => import('./letters/A'))to
const A = component_1.default(() => Promise.resolve().then(() => __importStar(require('./letters/A'))));Then
@loadable/babel-plugincan't detectloadableMy Solution
tsconfig.json
It don't change
loadable(() => import('something')so the detection is enable compile normally.I wish help someone like me.
And I think it's needed a guide to this for someone who use typescript.