Implicit code sharing with webpack, router-responder-router

Edit2: The regular expression has been edited to match the path of the window file and the code is split. But my child components in my root path will still not load.

Edit: My code has changed from last week, but I still stick to this problem (and I need to declare my routes in a declarative way, so using JSX).

First of all, I use Webpack 1.x with React, a reactive router, a packet loader, Babel6, ES6 and airbnb-eslint-config.

I tried after the Henley Edition article about code fragments and loading (with its example repo ), based on Respond to a huge sample application .

But I failed to make bundle-loader split my code into pieces ...

Here is my code:

webpack.config.js

const webpack = require('webpack'); const path = require('path'); const nodeDir = `${__dirname}/node_modules`; const routeComponentRegex = /src[\/\\]views[\/\\]([^\/\\]+)[\/\\]js[\/\\]([^\/\\]+).js$/; const paths = [ // Only to test which files match the regex, juste in case 'src/views/index/js/Index.js', 'src/views/login-page/js/LoginForm.js', 'src/common/main-content/js/MainContent.js', 'src/routes/main.js', ]; console.log(routeComponentRegex.test(paths[0])); // prints 'true' console.log(routeComponentRegex.test(paths[1])); // prints 'true' console.log(routeComponentRegex.test(paths[2])); // prints 'false' console.log(routeComponentRegex.test(paths[3])); // prints 'false' const config = { resolve: { alias: { react: `${nodeDir}/react`, 'react-dom': `${nodeDir}/react-dom`, 'react-router': `${nodeDir}/react-router`, 'react-fetch': `${nodeDir}/react-fetch`, 'react-cookie': `${nodeDir}/react-cookie`, 'react-bootstrap': `${nodeDir}/react-bootstrap`, 'react-bootstrap-daterangepicker': `${nodeDir}/react-bootstrap-daterangepicker`, 'react-bootstrap-datetimepicker': `${nodeDir}/react-bootstrap-datetimepicker`, velocity: `${nodeDir}/velocity-animate`, moment: `${nodeDir}/moment`, slimscroll: `${nodeDir}/slimscroll`, }, }, entry: { app: './client/src/routes/js/main', vendors: [ 'react', 'react-dom', 'react-router', 'react-fetch', 'react-cookie', 'react-bootstrap', 'react-bootstrap-daterangepicker', 'react-bootstrap-datetimepicker', 'velocity', 'moment', 'slimscroll', ], }, output: { path: path.join(__dirname, 'public/dist'), publicPath: '/dist/', filename: 'bundles/[name].bundle.js', chunkFilename: 'chunks/[name].chunk.js', }, module: { loaders: [ { test: /\.js$/, include: path.join(__dirname, 'client'), exclude: routeComponentRegex, loader: 'babel', }, { test: /\.css$/, include: path.join(__dirname, 'client'), exclude: routeComponentRegex, loader: 'style!css-loader?modules&importLoaders=1' + '&localIdentName=[name]__[local]___[hash:base64:5]', }, { test: routeComponentRegex, include: path.join(__dirname, 'client'), loaders: ['bundle?lazy', 'babel'], }, ], }, plugins: [ new webpack.optimize.CommonsChunkPlugin('vendors', 'bundles/vendors.js', Infinity), ], }; module.exports = config; 

client / src / views / main content /JS/MainContent.js

 import React from 'react'; import { Link } from 'react-router'; const MainContent = (props) => ( <div> <h1>App</h1> <ul> <li><Link to="/login">Login</Link></li> </ul> {props.children} </div> ); MainContent.propTypes = { children: React.PropTypes.node.isRequired, }; export default MainContent; 

public / src / views / index / js / index.js

 import React from 'react'; const Index = () => ( <h2>Index Page</h2> ); export default Index; 

public / src / views / login / js / login.js

 import React from 'react'; const LoginForm = () => ( <div className="box box-default"> <h2>Login Page</h2> </div> ); export default LoginForm; 

Entry Point (client / src / routes / main.js):

 import React from 'react'; import { render } from 'react-dom'; import { Router, Route, IndexRoute, browserHistory } from 'react-router'; import MainContent from '../../common/main-content/js/MainContent'; // modules supposed to be loaded lazily import Index from '../../views/index/js/Index'; import Login from '../../views/login/js/Login'; import ShortOffers from '../../views/short-offers/js/ShortOffers'; import CreateJobOffer from '../../views/create-job-offer/js/CreateJobOffer'; function lazyLoadComponent(lazyModule) { return (location, cb) => { lazyModule(module => { cb(null, module); }); }; } function lazyLoadComponents(lazyModules) { return (location, cb) => { const moduleKeys = Object.keys(lazyModules); const promises = moduleKeys.map(key => new Promise(resolve => lazyModules[key](resolve)) ); Promise.all(promises).then(modules => { cb(null, modules.reduce((obj, module, i) => { obj[moduleKeys[i]] = module; return obj; }, {})); }); }; } render(( <Router history={browserHistory}> <Route path="/" component={MainContent}> <IndexRoute getComponent={lazyLoadComponent(Index)} /> <Route path="short-offers" getComponent={lazyLoadComponent(ShortOffers)} /> <Route path="create-job-offer" getComponent={lazyLoadComponent(CreateJobOffer)} /> </Route> <Route path="login" getComponent={lazyLoadComponent(Login)} /> </Router> ), document.getElementById('content')); 

Now webpack output:

 Hash: a885854f956aa8d2a00c Version: webpack 1.13.0 Time: 6321ms Asset Size Chunks Chunk Names bundles/app.bundle.js 84.7 kB 0 [emitted] app bundles/vendors.js 2.55 MB 1 [emitted] vendors chunk {0} bundles/app.bundle.js (app) 89 kB {1} [rendered] [0] multi app 28 bytes {0} [built] + 26 hidden modules chunk {1} bundles/vendors.js (vendors) 2.45 MB [rendered] [0] multi vendors 148 bytes {1} [built] + 626 hidden modules 

See, there are no packages :( If I understand well, the third loader in webpack.config.js should take care of the files imported into the .js files and make them in chunks so that they can be loaded dynamically (and lazily) .

In addition, my pages do not load. If I cross out code that separates the image, it works:

 render(( <Router history={browserHistory}> <Route path="/" component={MainContent}> <IndexRoute component={Index} /> <Route path="short-offers" getComponent={ShortOffers} /> <Route path="create-job-offer" getComponent={CreateJobOffer} /> </Route> <Route path="login" getComponent={LoginPage} /> </Router> ), document.getElementById('content')); 

But my application will be huge, and I absolutely need to break the code.

Someone please ask me to tell?

Thanks in advance!

+7
reactjs webpack react-router
source share
2 answers

The author of the article is here. Try running npm start (it will start the dev server) or webpack -c webpack.config.js (it outputs files to the __build__ directory). I think you just forgot to specify webpack in the correct configuration file.

+1
source share

use module.exports instead of export default

 import React from 'react'; import { Link } from 'react-router'; const MainContent = (props) => ( <div> <h1>App</h1> <ul> <li><Link to="/login">Login</Link></li> </ul> {props.children} </div> ); MainContent.propTypes = { children: React.PropTypes.node.isRequired, }; module.exports = MainContent; 

or better to use the babel-plugin-add-module-exports , it converts

 // index.js export default 'foo' 

in

 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 'foo'; 
0
source share

All Articles