Using Webpack 2 and React Router v4 I have been able to set up working code splitting. There is an intermediate <AsyncComponent>
that resolves the promise and returns the component (a pattern found on github issues).
An example set of routes below:
<Switch>
<Route
path="me"
render={(props) =>
<AsyncComponent promise={ require.ensure([], (require) => require('./modules/Profile'), 'profile') } props={props} />
}
/>
<Route
path="credit-card"
render={(props) =>
<AsyncComponent promise={ require.ensure([], (require) => require('./modules/CreditCard'), 'credit-card') } props={props} />
}
/>
</Switch>
I would like to extend that further, and for certain routes only, load in additional libraries. In the example above, I would like to fetch the StripeJS (https://js.stripe.com/v2/) library only when on the credit card route.
I want to emphasise that I can load Stripe directly into the footer and all works normally. There are multiple libraries, I'm using Stripe as an easy to digest example.
The following has been attempted to little success:
<script>
with a src
attribute, wait for it to load, then let the component do its thing. This works ok, but is really horrible from a maintainability (if two or more libraries are needed, I then need to replicate the clumsy manual script
load) point of view and seems to work against the webpack "way". const core = [
'lodash',
'react',
'react-dom',
'axios',
'react-router-dom',
];
const config = {
context: path.resolve(__dirname, './ts_build'),
node: {
fs: "empty"
},
entry: {
app: './app.js',
core: core,
},
output: {
filename: '[name].js',
chunkFilename: '[name].[id].chunk.js',
path: path.resolve(__dirname, './../../public'),
publicPath: 'http://example.org/',
},
resolve: {
modules: [
path.resolve('./src'),
],
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['core'],
minChunks: Infinity,
}),
new webpack.NamedModulesPlugin(),
],
};
To restrict access to routes in React Router, we set the render prop to a function that renders the component we want according to the condition we're checking. import { Route, Redirect } from "react-router"; <Route exact path="/" render={() => (loggedIn ?
Path: /src/_components/PrivateRoute.jsx The react private route component renders child components ( children ) if the user is logged in. If not logged in the user is redirected to the /login page with the return url passed in the location state property.
You should not use route or withrouter() or Link outside a router. React router throws the error, “you should not use route or withrouter() outside a router” when you have not defined BrowserRouter and still using Link or NavLink or Router components.
https://github.com/hinok/webpack2-react-router-code-splitting
Repository contains webpack2
+ react-router v4
+ implemented code splitting
using dynamic import() and loading external libraries on demand only once by using loadjs. As example it loads Stripe.js
for specific route.
In repository you can find two ways to do code splitting
It's based on official Webpack documentation and gist by Andrew Clark
While preparing that repository I found that @Chris would like to load Stripe.js
only for certain routes which is hosted on external CDN. Since then I've been thinking about the best way to use also AMD modules and avoid leaking global variables but this is a bit tricky because each AMD module could have different wrapper, by saying wrapper I mean something like:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['b'], function (b) {
return (root.amdWebGlobal = factory(b));
});
} else {
root.amdWebGlobal = factory(root.b);
}
}(this, function (b) {
return {};
}));
I could say that UMD wrapper is kind of standard but sometimes people prefer less opinionated wrappers or they just don't care about other environments. I'm mentioning it because in the git history, you can find commit called Amdify which was more proof of concept how AMD env could be simulated. Finally I decided to remove it because it's far from ideal and it doesn't cover all usages and edge cases.
I couldn't find any information about integrating external AMD modules or using AMD modules in some way with webpack. On the contrary I found that it will just not work
@mc-zone you should be able to load AMD modules with script.js. But this has nothing to do with webpack, it just works because AMD was designed for this. Thus you won't be able to use webpack features inside these AMD modules. webpack requires static analysis on build time.
by @jhns see on github
webpack doesn't handle script loading. Use an separate library for this. i. e. https://github.com/ded/script.js/
by @sokra see on github
If it's not possible you should not require() it but load it via a script-loader like script.js.
by @jhns see on github
Related issues on Github:
Today I found an article by James Kale on medium about his project react-loadable which do almost the same thing as LazilyLoad
component but with promise that
I highly recommend checking it out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With