webpack: "Uncaught SyntaxError: Unexpected token <" error happened sometimes
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
<!DOCTYPE html>
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 :
When this error happened, webpack usually occur build repeat :
Error show on <!DOCTYPE html> :
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 18
- Comments: 23
Commits related to this issue
- Fixes reloading URLs (and autoreload) from dev server Thanks to this post here: https://github.com/webpack/webpack/issues/2882#issuecomment-280906981 — committed to CottageClass/cottageclass-map-vue by holmesworcester 5 years ago
- fix: add base tag for reload events issue - https://github.com/webpack/webpack/issues/2882 — committed to minsoftk/develog by minsoftk 2 years ago
- fix: #330 caching results in white page, see webpack/webpack#2882 (comment) — committed to Sybit-Education/Diveni by deleted user 10 months ago
- fix: #330 caching results in white page, see webpack/webpack#2882 (comment) (#387) Co-authored-by: Schoch, Kevin <kevin.schoch@sybit.de> — committed to Sybit-Education/Diveni by KzuDemEvin 10 months ago
I have a same problem fix with added
<base href="/" />
into the<head>
of myindex.html
It’s because html 5 routing … search for it
@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.
@hemedani May you please elaborate on why and how it works? Did it for me, asking out of curiosity. Thank you.
I am currently having this issue. I tried the base tag and the
output: { publicPath: '/' }
and they both aren’t working.@hemedani unbelievable, after i added this line, and it worked as well.
If someone still has the same problem ) I had this code:
and it was not working. But then I changed it to:
And it finally works! .get(*) should be declare after /use(“/”)
@hemedani How do i do this using webpack? Is there a plugin to insert the
base
tag?@hemedani same problem too, How to do??
@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.