Alessander Franca
Alessander Franca

Reputation: 2753

webpack 2 react code splitting

I am trying to split the react code at routes but I am receiving this error: Uncaught SyntaxError: Unexpected token <

Here is my webpack code:

var path = require('path')
var webpack = require('webpack')
var HappyPack = require('happypack')
var BundleTracker = require('webpack-bundle-tracker')
var path = require('path')
var ExtractTextPlugin = require("extract-text-webpack-plugin")
var polyfill = require("babel-polyfill")

function _path(p) {
  return path.join(__dirname, p);
}

module.exports = {

    context: __dirname,
    entry: {
        index: './assets/js/index',
    }, 

    output: {
        path: path.resolve('./assets/bundles/'), 
        filename: '[name]-[hash].js'
    },

    devtool: 'inline-eval-cheap-source-map',

    plugins: [
        new BundleTracker({filename: './webpack-stats.json'}), 
        new webpack.ProvidePlugin({ 
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery' 
        }),
        new HappyPack({
            threads: 4,
            loaders: [ 'babel-loader' ],
        }),
        new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /pt-br/)
    ],

    module: {
        rules: [

             {
                test: /\.css$/,
                include: path.resolve(__dirname, './assets/css/'),
                use: ["style-loader", "css-loader", "resolve-url-loader"]
                // use: ExtractTextPlugin.extract({ fallbackLoader: "style-loader", loader: ["css-loader", "resolve-url-loader"]})
            },

            {
                test: /\.scss$/,
                include: path.resolve(__dirname, './assets/css/'),
                use: ["style-loader", "css-loader", "resolve-url-loader", "sass-loader"]
                // use: ExtractTextPlugin.extract({ fallbackLoader: "style-loader", loader: ["css-loader", "resolve-url-loader", "sass-loader"]})
            },

            {
                test: /\.scss$/,
                include: path.resolve(__dirname, './assets/vendors/'),
                use: ["style-loader", "css-loader", "resolve-url-loader", "sass-loader"]
                // use: ExtractTextPlugin.extract({ fallbackLoader: "style-loader", loader: ["css-loader", "resolve-url-loader", "sass-loader"]})
            },

            {
                test: /\.jsx?$/, 
                include: path.resolve(__dirname, './assets/js/'),
                exclude: /node_modules/, 
                use: [{
                  loader: 'happypack/loader',
                }]
            },
            {
                test: /\.png$/,
                use: { 
                        loader: 'file-loader' ,
                        options: {
                            name: '/static/img/[name].[ext]'
                        }
                    }

            }
        ]
    },

    resolve: {
        extensions: ['.js', '.jsx'],
        modules: [ path.resolve(__dirname, 'node_modules')]
    }   
}

My babelrc code:

{
  "presets": [
                ["es2015", {modules: false}],
                "react"
            ]
}

And my router:

<Router history={browserHistory}>
        <Route path="login" onEnter={redirectHome} getComponent={(location, cb) => {
              System.import('./components/common/LoginPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
    <Route path="app" onEnter={requireAuth} getComponent={(location, cb) => {
              System.import('./components/App')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          }>
      <IndexRoute getComponent={(location, cb) => {
              System.import('./components/middle/dashboard/DashboardPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          }/>
      <Route path="clients">
          <IndexRoute getComponent={(location, cb) => {
              System.import('./components/middle/clients/ClientPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          <Route path="form/:method(/:clientId)" getComponent={(location, cb) => {
              System.import('./components/middle/clients/ClientForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          <Route path="detail/:id" getComponent={(location, cb) => {
              System.import('./components/middle/clients/ClientDetail')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          <Route path="attends/:clientId" getComponent={(location, cb) => {
              System.import('./components/middle/attends/ClientAttend')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
      </Route>
      <Route path="contacts">
            <Route path="form/:method/:client(/:contactId)" getComponent={(location, cb) => {
              System.import('./components/middle/contacts/ContactForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="list/:id" getComponent={(location, cb) => {
              System.import('./components/middle/contacts/ContactPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="detail/:id/:contactId" getComponent={(location, cb) => {
              System.import('./components/middle/contacts/ContactDetail')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
        </Route>
        <Route path="transmissors">
          <Route path="form/:method/:client(/:transmissorId)" getComponent={(location, cb) => {
              System.import('./components/middle/transmissors/TransmissorForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          <Route path="list/:id" getComponent={(location, cb) => {
              System.import('./components/middle/transmissors/TransmissorPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="detail/:client(/:transmissorId)" getComponent={(location, cb) => {
              System.import('./components/middle/transmissors/TransmissorDetail')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
        </Route>
        <Route path="attends">
            <IndexRoute getComponent={(location, cb) => {
              System.import('./components/middle/attends/AttendancePage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="call/:id(/:attend)" getComponent={(location, cb) => {
              System.import('./components/middle/attends/AttendanceDetail')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          </Route>
          <Route path="reports">
            <IndexRoute getComponent={(location, cb) => {
              System.import('./components/middle/reports/ReportPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="list/alarms/:filter" getComponent={(location, cb) => {
              System.import('./components/middle/reports/ReportAlarm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="list/attendants/:filter" getComponent={(location, cb) => {
              System.import('./components/middle/reports/ReportAttendant')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="list/clients/:filter" getComponent={(location, cb) => {
              System.import('./components/middle/reports/ReportClient')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          </Route>
          <Route path="user/form/:method(/:userId)" getComponent={(location, cb) => {
              System.import('./components/middle/user/UserForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          <Route path="manage">
            <Route path="phones" getComponent={(location, cb) => {
              System.import('./components/middle/user/UserForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />     
            <Route path="attend" getComponent={(location, cb) => {
              System.import('./components/middle/manage/ManageAttend')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
            <Route path="alarms" getComponent={(location, cb) => {
              System.import('./components/middle/manage/AlarmManagement')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />      
          </Route>
          <Route path="events">
            <Route path="detail/:id" getComponent={(location, cb) => {
              System.import('./components/middle/events/EventsPage')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          </Route>
          <Route path="alarms">
            <Route path="form/:method(/:alarmId)" getComponent={(location, cb) => {
              System.import('./components/middle/manage/AlarmForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          </Route>
          <Route path="phones">
            <Route path="form/:method(/:phoneId)" getComponent={(location, cb) => {
              System.import('./components/middle/manage/PhoneForm')
                .then(loadRoute(cb))
                .catch(errorLoading);
            }
          } />
          </Route>
    </Route>
    <Route path="*" onEnter={redirect}/>
    </Router>

I am using django at backend side, and the webpack-bundle-tracker that has not support for webpack code splitting.

So I create an issue and did a solution (or workaround) for this: https://github.com/owais/webpack-bundle-tracker/issues/19

My index.html is:

{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no" />
    <title>title</title>
    <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
    {% render_bundle 'index' 'css' %}
  </head>

  <body>
    <div id ="app" class="app"></div>
    <audio id="audio_sip" autoplay="autoplay"></audio>
    {% render_bundle 'index' 'js' %}
    {% render_bundle 'split' 'js' %}
  </body>
</html>

So I do not know if I am using the import correctly at react router or the problem can something related to django.

Can anyone hep me?

Thanks in advance.

Upvotes: 1

Views: 517

Answers (2)

hazardous
hazardous

Reputation: 10837

This may be a side-effect of not having absolute paths in the auto-inserted script references in the generated index.html. E.g. if the generated script statement is <script src="./index.js"></script>, then when you are on a subroute say /contacts and there's a refresh, the browser will ask for /contacts/index.js. If your server instead sends back index.html, then the browser will fail trying to parse html as JS and will complain about the invalid < character.

To verify this, hard-code the absolute references in the index.html file, like so - <script src="/index.js"></script>, then refresh to check if the issues still exist.

If this indeed turns out to be the case, please read up on how to modify the index.html template to insert absolute paths, as I am afraid I am not familiar with the template syntax you are using.

One fix which should work is to have output.publicPath = "/" configuration in your webpack.config.js file. This should make the script path absolute.

A similar issue is Issue using nested routes in React-Router with webpack.

Upvotes: 2

Merrick Christensen
Merrick Christensen

Reputation: 511

Typically the error on "<" is an indicator that it's not able to parse. Which would mean babel + react config probably isn't running on the file. When you look at your webpack config babel is only run on jsx. Since you aren't adding that extension when you lazily old it isn't run through that loader. You can either change your regular expression to run all js files through babel, excluding node or you can explicitly add the .jsx extension when you import files.

Upvotes: 0

Related Questions