whilelucky / pwa

An opinionated progressive web app boilerplate
MIT License
357 stars 47 forks source link

Issue with common chunk plugin #6

Closed AnuragSinghTomarr closed 7 years ago

AnuragSinghTomarr commented 7 years ago

Hi i am trying to modify the webpackclient.js file.

  entry: {
    main: './client/index.js',
    vendor: ['./client/vendor/js/index.js', './client/vendor/css/index.css'],
    modOne: './client/views/Chunk.js',
  }

In the entry i have added one more entry point modOne which contains chunk.js chunk.js is contains present the view folder which imports these from the same view folder.

import Detail from './Detail/Detail';
import NotFoundPage from './NotFoundPage/NotFoundPage';

Changes i made in the route folder are

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import importCss from 'core/importCss';
import Wrapper from 'views/Wrapper/Wrapper';
import NotFoundPage from 'views/NotFoundPage/NotFoundPage';
import Detail from 'views/Detail/Detail';
export default (
  <Route path="/" component={Wrapper}>

    <Route
      name="landing"
      getComponent={(_, cb) => {
        Promise.all([
          import('views/LandingPage/LandingPage' /* webpackChunkName: 'landing' */),
          importCss('landing'),
        ]).then(([module]) => cb(null, module.default));
      }}
    />
    <IndexRoute name="modOne" component={Detail} />
    <Route name="modOne" path="*" component={NotFoundPage} />

  </Route>
);

Here is the common chunk configuration

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new CleanWebpackPlugin(['./build/client']),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': isProd ? '"production"' : '"development"',
      __BROWSER__: true,
      __PWA_ENV__: JSON.stringify(__PWA_ENV__),
      __LOCAL__: __PWA_ENV__ === 'local',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names: ['vendor', 'webpackManifest'],
      minChunks: Infinity,
    }),
    // new webpack.optimize.CommonsChunkPlugin({
    //   name: 'main',
    //   children: true,
    //   minChunks: 2,
    // }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'modOne',
      chunks: ['main', 'modOne'],
      minChunks: 2,
    }),

but the issue is that when i make a build and run the code on localhost:1377 i get a error in the console as -

webpackManifest.afbe5cc0.js:formatted:10 Uncaught TypeError: Cannot read property 'call' of undefined
    at n (webpackManifest.afbe5cc0.js:formatted:10)
    at Object.6rQ3 (main.bf018efd.js:1)
    at n (webpackManifest.afbe5cc0.js:formatted:10)
    at window.webpackJsonp (webpackManifest.afbe5cc0.js:formatted:26)
    at main.bf018efd.js:1

Please let me know what wrong i am doing with common chunk plugin.

whilelucky commented 7 years ago

I see the problem but you haven't mentioned what it is that you're trying to achieve. Are you simply trying to add a new route? Or are you trying to add a new chunked route?

AnuragSinghTomarr commented 7 years ago

Thanks lakshya u looked into it. What i want to achieve is that suppose i am on pageA from which when i navigate i go to pageB then as soon as i navigate pageB bundle is downloaded, now from pageB i navigate to pageC so now pageC bundle is downloaded. There is no problem with this approach as in the route we can lazy import these bundles as per the route. What i want is PageA bundle contains PageB and PageC bundles also so that when i navigate from PageA to PageB then i already have PageB bundle. So bro let me know what i am doing wrong with mine webpack configuration.

whilelucky commented 7 years ago

The recommended approach to do this is to to wait for the LandingPage(PageA) route to render and then explicitly lazy import all the other routes FindPage and SearchPage(PageB and PageC) in the second .then of the LandingPage. For example:

<IndexRoute
  name="landing"
  getComponent={(_, cb) => {
    Promise.all([
      import('./views/LandingPage/LandingPage' /* webpackChunkName: 'landing' */),
      importCss('landing'),
    ]).then(([module]) => cb(null, module.default)).then(() => {
      import('./views/FindPage/FindPage' /* webpackChunkName: 'find' */);
      importCss('find');
      import('./views/CitiesPage/CitiesPage' /* webpackChunkName: 'cities' */);
      importCss('cities');
    });
  }}
/>

<Route
  name="find"
  path="/find/"
  getComponent={(_, cb) => {
    Promise.all([
      import('./views/FindPage/FindPage' /* webpackChunkName: 'find' */),
      importCss('find'),
    ]).then(([module]) => cb(null, module.default));
  }}
/>

<Route
  name="cities"
  path="/cities/"
  getComponent={(_, cb) => {
    Promise.all([
      import('./views/CitiesPage/CitiesPage' /* webpackChunkName: 'cities' */),
      importCss('cities'),
    ]).then(([module]) => cb(null, module.default));
  }}
/>

Advantage of this approach compared to bundling the 3 routes together is that you still keep separate chunks which means your time to first interactivity is still low. And, the other routes are lazy loaded on DOMContentLoaded so you're not competing for bandwidth with other critical resources.

AnuragSinghTomarr commented 7 years ago

Thanks bro... 👍