Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Uncaught SyntaxError: Unexpected token <" error happened sometimes #2882

Closed
ghost opened this issue Aug 17, 2016 · 18 comments
Labels

Comments

@ghost
Copy link

@ghost ghost commented Aug 17, 2016

Currently I am working with webpack2 (beta-20) + React + express to create an universal web app. But when I build my script in development environment, sometimes I got an error

Uncaught SyntaxError: Unexpected token <

When I look into the file, it show the error occurs on

And this error will happened in both development and production. And when I remove all of the [hash] and [chunkhash], this error won't happened. I don't know why, does anyone has solution for this problem?

Here's my webpack.config.js :

const path = require('path');
const webpack = require('webpack');
const AssetsPlugin = require('assets-webpack-plugin');
const del = require('del');

const nodeEnv = process.env.NODE_ENV || 'development';
const isDev = nodeEnv !== 'production';

const rootPath = path.join(__dirname);
const srcPath = path.join(rootPath, './src');
const staticPath = path.join(rootPath, './static');
const cleanPath = [
  path.join(staticPath, './*'),
  path.join('!', staticPath, './favicon.ico'),
  path.join('!', staticPath, './assets.js'),
];

// The plug of cleaning static files, it used for production settings
class CleanPlugin {
  constructor(options) {
    this.options = options;
  }

  apply() {
    del.sync(this.options.files);
  }
}

// Setting the plugins for development and prodcution
function getPlugins() {
  const plugins = [];

  plugins.push(
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(nodeEnv) },
      __DEV__: JSON.stringify(isDev),
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: isDev ? '[name].[hash].js' : '[name].[chunkhash].js',
      minChunks: Infinity,
    }),
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new AssetsPlugin({
      filename: 'assets.js',
      path: staticPath,
      processOutput: assets => `module.exports = ${JSON.stringify(assets)};`,
    })
  );

  if (isDev) {
    plugins.push(
      new webpack.HotModuleReplacementPlugin()
    );
  } else {
    plugins.push(
      new CleanPlugin({ files: cleanPath }),
      new webpack.LoaderOptionsPlugin({
        minimize: true,
        debug: false,
      }),
      new webpack.optimize.UglifyJsPlugin({
        compress: { screw_ie8: true, warnings: false },
        output: { comments: false },
        sourceMap: false,
      }),
      new webpack.optimize.DedupePlugin()
    );
  }

  return plugins;
}

// Webpack settings
module.exports = {
  cache: isDev,
  debug: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: srcPath,
  entry: {
    app: isDev ? [
      'react-hot-loader/patch',
      'webpack-hot-middleware/client',
      './client.js',
    ] : './client.js',
    vendor: [
      'react', 'react-dom',
      'redux', 'react-redux',
      'redux-thunk',
      'react-router',
      'react-router-redux',
      'react-helmet',
      'axios',
    ],
  },
  output: {
    path: staticPath,
    publicPath: '/',
    filename: isDev ? '[name].[hash].js' : '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
  },
  module: {
    preLoaders: [
      { test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/ },
    ],
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [['es2015', { modules: false }], 'react', 'stage-0'],
          plugins: ['transform-runtime', 'react-hot-loader/babel'],
        },
      },
    ],
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.scss'],
    modules: [
      srcPath,
      'node_modules',
    ],
  },
  plugins: getPlugins(),
  eslint: { failOnError: true },
};

Here's my server.js :

import path from 'path';
import express from 'express';
import favicon from 'serve-favicon';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { match, RouterContext } from 'react-router';
import routes from './routes';
import config from './config';
import configureStore from './configureStore';
import renderHtmlPage from './renderHtmlPage';

const app = express();

app.use(favicon(path.join(__dirname, '../static/favicon.ico')));
app.use('/static', express.static(path.join(__dirname, '../static')));

// Run express as webpack dev server
if (__DEV__) {
  const webpack = require('webpack');
  const webpackConfig = require('../webpack.config');

  const compiler = webpack(webpackConfig);

  app.use(require('webpack-dev-middleware')(compiler, {
    publicPath: webpackConfig.output.publicPath,
    noInfo: true,
    hot: true,
    stats: { colors: true },
  }));

  app.use(require('webpack-hot-middleware')(compiler));
}

// Render content
app.get('*', (req, res) => {
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message);
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search);
    } else if (!renderProps) {
      res.sendStatus(404);
    } else {
      const store = configureStore();

      const promises = renderProps.components
        .filter(component => component.fetchData)
        .map(component => component.fetchData(store.dispatch, renderProps.params));

      Promise.all(promises)
        .then(() => {
          const content = renderToString(
            <Provider store={store}>
              <RouterContext {...renderProps} />
            </Provider>
          );
          const initialState = store.getState();

          res.status(200).send(renderHtmlPage(content, initialState));
        });
    }
  });
});

if (config.port) {
  app.listen(config.port, config.host, err => {
    if (err) console.error(`==> 😭  OMG!!! ${err}`);

    console.info(`==> 🌎  Listening at http://${config.host}:${config.port}`);
  });
} else {
  console.error('==> 😭  OMG!!! No PORT environment variable has been specified');
}

Here's my client.js :

import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';
import configureStore from './configureStore';
import routes from './routes';

const initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState, routerReducer);
const history = syncHistoryWithStore(browserHistory, store);

const renderApp = (CurrentAppRoutes: any) => {
  render(
    <AppContainer>
      <Provider store={store}>
        <Router history={history} routes={CurrentAppRoutes} />
      </Provider>
    </AppContainer>,
    document.getElementById('react-view')
  );
};

renderApp(routes);

// Enable hot reload by react-hot-loader
if (__DEV__) {
  if (module.hot) {
    module.hot.accept('./routes', () => {
      const NextAppRoutes = require('./routes').default;

      renderApp(NextAppRoutes);
    });
  }
}

Here's my renderHtmlPage.js :

import Helmet from 'react-helmet';
import assets from '../static/assets';

export default (content, initialState) => {
  const head = Helmet.rewind();

  // Setup html page
  return `
    <!DOCTYPE html>
    <html ${head.htmlAttributes.toString()}>
      <head>
        <meta char-set="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <meta http-equiv="Content-Language" content="en" />
        <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

        ${head.base.toString()}
        ${head.title.toString()}
        ${head.meta.toString()}
        ${head.link.toString()}
      </head>
      <body>
        <div id="react-view">${content || null}</div>

        <script type="text/javascript">
          ${initialState && `window.__INITIAL_STATE__=${JSON.stringify(initialState)}`}
        </script>

        <!--[if gte IE 9 ]>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-sham.min.js"></script>
        <![endif]-->

        ${assets && `<script src="${assets.vendor.js}"></script>`}
        ${assets && `<script src="${assets.app.js}"></script>`}
        ${head.script.toString()}
      </body>
    </html>
  `;
};

Here's the error message from Chrome :
2016-08-17 6 09 35

When this error happened, webpack usually occur build repeat :
2016-08-17 6 09 55

Error show on :
2016-08-17 10 45 55

@ghost ghost changed the title "Uncaught SyntaxError: Unexpected token <" happened in sometimes "Uncaught SyntaxError: Unexpected token <" happened sometimes not everytime Aug 17, 2016
@sokra sokra added question and removed bug webpack-2 labels Aug 17, 2016
@ghost ghost changed the title "Uncaught SyntaxError: Unexpected token <" happened sometimes not everytime "Uncaught SyntaxError: Unexpected token <" happened sometimes Aug 17, 2016
@ghost ghost changed the title "Uncaught SyntaxError: Unexpected token <" happened sometimes "Uncaught SyntaxError: Unexpected token <" error happened sometimes Aug 17, 2016
@JimmyDaddy

This comment has been minimized.

Copy link

@JimmyDaddy JimmyDaddy commented Aug 18, 2016

I have this problem too, did you get a solution?

@ghost

This comment has been minimized.

Copy link
Author

@ghost ghost commented Aug 18, 2016

@CJHJim,

Not yet, I am still trying to find the cause

@ghost

This comment has been minimized.

Copy link
Author

@ghost ghost commented Aug 18, 2016

Hi @CJHJim,

I have solved the error, I use webpack-isomorphic-tools instead of assets-webpack-plugin (It's a good tool, but I might don't know how to config it webpack-2), here's my updated webpack.config :

/* eslint max-len:0 */

const path = require('path');
const webpack = require('webpack');

const nodeEnv = process.env.NODE_ENV || 'development';
const isDev = nodeEnv !== 'production';

const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./webpackIsomorphicTools.config')).development(isDev);

const rootPath = path.join(__dirname, '..');
const srcPath = path.join(rootPath, './src');
const distPath = path.join(rootPath, './public/dist');

// Setting the plugins for development and prodcution
function getPlugins() {
  const plugins = [];

  plugins.push(
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(nodeEnv) },
      __DEV__: JSON.stringify(isDev),
    }),
    /* new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: isDev ? '[name].[hash].js' : '[name].[chunkhash].js',
      minChunks: Infinity,
    }), */
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    webpackIsomorphicToolsPlugin
  );

  if (isDev) {
    plugins.push(
      new webpack.HotModuleReplacementPlugin()
    );
  } else {
    plugins.push(
      new webpack.LoaderOptionsPlugin({
        minimize: true,
        debug: false,
      }),
      new webpack.optimize.UglifyJsPlugin({
        compress: { screw_ie8: true, warnings: false },
        output: { comments: false },
        sourceMap: false,
      }),
      new webpack.optimize.DedupePlugin()
    );
  }

  return plugins;
}

// Webpack settings
module.exports = {
  cache: isDev,
  debug: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: srcPath,
  entry: {
    main: isDev ? [
      'webpack-hot-middleware/client',
      'react-hot-loader/patch',
      './client.js',
    ] : './client.js',
    /* vendor: [
      'react', 'react-dom',
      'redux', 'react-redux',
      'redux-thunk',
      'react-router',
      'react-router-redux',
      'react-helmet',
      'axios',
    ], */
  },
  output: {
    path: distPath,
    publicPath: '/dist/',
    filename: isDev ? '[name].[hash].js' : '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
  },
  module: {
    preLoaders: [
      { test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/ },
    ],
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [['es2015', { modules: false }], 'react', 'stage-0'],
          plugins: ['transform-runtime', 'react-hot-loader/babel'],
        },
      },
    ],
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.scss'],
    modules: [
      srcPath,
      'node_modules',
    ],
  },
  plugins: getPlugins(),
  eslint: { failOnError: true },
};
@ghost ghost closed this Aug 18, 2016
@ryanlewis

This comment has been minimized.

Copy link

@ryanlewis ryanlewis commented Aug 18, 2016

@wellyshen what changes did you make to resolve your problem?

@ghost

This comment has been minimized.

Copy link
Author

@ghost ghost commented Aug 18, 2016

@ryanlewis I change the universal manifest plugin from assets-webpack-plugin to webpack-isomorphic-tools, I think my problem is I don't know how to set the assets-webpack-plugin with webpack-2 properly.

@JimmyDaddy

This comment has been minimized.

Copy link

@JimmyDaddy JimmyDaddy commented Aug 19, 2016

@wellyshen I found this is a "404" problem, the Router needed a javaScript file named '1.app.js' but got a html file, I checked this html file and found that's my default '404' error page.

@ghost

This comment has been minimized.

Copy link
Author

@ghost ghost commented Aug 19, 2016

@CJHJim It seems your router doesn't find the file from http request, so it return your error page back, if you are using react-router, I suggest you to get realize how it works.

@JimmyDaddy

This comment has been minimized.

Copy link

@JimmyDaddy JimmyDaddy commented Aug 19, 2016

@wellyshen I known the point, it just happened on the builded files, if I run it on development it works.
I think there was something wrong on my webpack's config.....

@ghost

This comment has been minimized.

Copy link
Author

@ghost ghost commented Aug 19, 2016

@CJHJim Did you use hash or chunkhash on production environment? If you did, you need webpack-isomorphic-tools to handle it or your html file can't access the bundled js file.

@hemedani

This comment has been minimized.

Copy link

@hemedani hemedani commented Feb 19, 2017

I have a same problem fix with
added <base href="/" /> into the <head> of my index.html

@Hideer

This comment has been minimized.

Copy link

@Hideer Hideer commented Mar 20, 2018

@hemedani same problem too, How to do??

@xemasiv

This comment has been minimized.

Copy link

@xemasiv xemasiv commented May 17, 2018

@hemedani May you please elaborate on why and how it works?
Did it for me, asking out of curiosity. Thank you.

@hemedani

This comment has been minimized.

Copy link

@hemedani hemedani commented May 19, 2018

It's because html 5 routing ...
search for it

@jandiralceu

This comment has been minimized.

Copy link

@jandiralceu jandiralceu commented Oct 11, 2018

@hemedani many many many thanks, dude! It solves my trouble!!!

@SalmanCse

This comment has been minimized.

Copy link

@SalmanCse SalmanCse commented Feb 5, 2019

,,,,,,,such type add but not solve @hemedani pls help error : ^ SyntaxError: Unexpected token <
@jayalakshmis

This comment has been minimized.

Copy link

@jayalakshmis jayalakshmis commented Feb 14, 2019

I have a same problem fix with
added <base href="/" /> into the <head> of my index.html

@hemedani How do i do this using webpack? Is there a plugin to insert the base tag?

@dark-swordsman

This comment has been minimized.

Copy link

@dark-swordsman dark-swordsman commented Apr 11, 2019

I am currently having this issue. I tried the base tag and the output: { publicPath: '/' } and they both aren't working.

@khanhpn

This comment has been minimized.

Copy link

@khanhpn khanhpn commented May 8, 2019

@hemedani unbelievable, after i added this line, and it worked as well.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.