Code Splitting ~ ReferenceError: System is not defined - reactjs

My code hit the error
ReferenceError: System is not defined
In line
<IndexRoute getComponent={(nextState, cb) => System.import('./containers/Home').then(module => cb(null, module))} />
How do I define System. Is it related to my webpack settings? Here how I put it
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var stylus = require('stylus');
module.exports = {
debug: true,
devtool: 'eval',
entry: {
"vendor": ["react", "react-router", 'react-dom'],
"app": ['webpack-dev-server/client?http://localhost:3000', 'webpack/hot/only-dev-server', './app/App.js']
},
output: {
pathinfo: true,
path: path.resolve(__dirname, 'public'),
filename: '[name].js',
publicPath: 'http://localhost:3000/'
},
plugins: [
new HtmlWebpackPlugin({
title: 'Welcome!',
template: './index_template.ejs',
inject: 'body'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.UglifyJsPlugin({
output: {
comments: false
},
compress: {
warnings: false
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.bundle.js'
})
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loaders: ['react-hot', 'babel']
},
{
test: /\.styl$/,
exclude: /(node_modules|bower_components)/,
// loader: 'style!css?resolve url?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]!postcss!stylus-loader'
loader: 'style!css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]!postcss!stylus-loader'
},
{
test: /\.(png|jpg)$/,
exclude: /(node_modules|bower_components)/,
loader: 'url-loader?name=images/[name].[ext]&limit=8192'
},
{
test: /\.(ttf|otf|eot)$/,
exclude: /(node_modules|bower_components)/,
loader: 'url-loader?name=fonts/[name].[ext]&limit=8192'
},
{
test: /\.css$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
},
{
test: /\.scss$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?resolve url'
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.js$/,
include: path.resolve('node_modules/mapbox-gl-shaders/index.js'),
loader: 'transform/cacheable?brfs'
}
]
},
resolve: {
root: path.join(__dirname, '..', 'app'),
alias: {
'react': path.join(__dirname, 'node_modules', 'react')
},
extensions: ['', '.js', '.jsx', '.json', '.css', '.styl', '.png', '.jpg', '.jpeg', '.gif']
},
stylus: {
'resolve url': true
},
postcss: function () {
return [autoprefixer];
}
};
(Disclaimer: I am new to React-Router and webpack, so this may be
obvious to someone with more familiarity)

Your webpack build stack probably doesn't have configured System.import. I suppose that you use webpack 1 and support of System.import will be only in webpack 2.
You can change your existing code to current popular code splitting solution:
<IndexRoute
getComponent={(nextState, cb) => {
require.ensure([], require => {
// default import is not supported in CommonJS standard
cb(null, require('./containers/Home').default)
});
}}
/>
Note that you must specify .default if you want to use default import in CommonJS standard.

Related

Webpack 5, Server-Side rendering, and FOUC

I'm upgrading an existing web site from Webpack 3 to Webpack 5.
The site uses server side rendering for the first load, the client side routing for any in-site navigation. All this worked fine with Webpack 3, but after migrating to Webpack 5 it looks like some of the styles are being applied via javascript and that's creating a FOUC during the first load (after that, in-site navigation works fine and looks correct). As a test, I turned off javascript in my browser; the old site loads fine and looks correct, but the upgraded site does not. It feels like I need style-loader in the server config somewhere, but when that's added, I get a "Cannot GET /" when trying to load the site. Any help is appreciated.
Server-side config
require('dotenv').config({ silent: true });
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const includePaths = [path.resolve(__dirname, 'stylesheets')];
module.exports = {
bail: true,
entry: {
main: './src/entry-server',
},
output: {
path: path.join(__dirname, 'build', 'prerender'),
filename: '[name].js',
publicPath: '/bundle/',
libraryTarget: 'commonjs2',
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
PRERENDER: true,
ASSETS_CDN_PREFIX: JSON.stringify(process.env.ASSETS_CDN_PREFIX || ''),
},
}),
// only load moment english locale: https://github.com/moment/moment/issues/2517
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(en)$/),
new webpack.optimize.ModuleConcatenationPlugin(),
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
],
module: {
rules: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
use: 'babel-loader',
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
},
},
'postcss-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.svg$/,
use: `svg-inline-loader?removeTags&removingTags[]=${['defs', 'style', 'title'].join(',removingTags[]=')}`,
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss', '.json'],
},
target: 'node',
};
Server entry point
export default function (req, res, environmentConstants, callback) {
// ...setup
match({ routes, location: targetUrl }, (error, redirectLocation, renderProps) => {
// ...setup
fetchSomeData().then(() => renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>,
))
.then((content) => {
callback(null, {
helmet: Helmet.renderStatic(),
content,
initialState: serialize(store.getState(), { isJSON: true }),
env: serialize(someEnvConstants),
});
})
Client-side config
require('dotenv').config({ silent: true });
const AssetsPlugin = require('assets-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const webpack = require('webpack');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const includePaths = [path.resolve(__dirname, 'stylesheets')];
// Match all routes that we want to lazy load
const lazyRouteRegex = /route\/([^/]+\/?[^/]+)Route.jsx$/;
module.exports = {
bail: true,
entry: {
main: './src/entry-client',
vendor: [
'react',
'react-dom',
'react-router',
'redux',
'react-redux',
'xmldom',
],
},
output: {
path: path.join(__dirname, 'build', 'public', '[fullhash]'),
filename: '[name].js',
chunkFilename: '[id].chunk.js',
publicPath: `${process.env.ASSETS_CDN_PREFIX || ''}/build/public/[fullhash]/`,
},
plugins: [
// only load moment english locale: https://github.com/moment/moment/issues/2517
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(en)$/),
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
PRERENDER: false,
ASSETS_CDN_PREFIX: JSON.stringify(process.env.ASSETS_CDN_PREFIX || ''),
},
}),
new AssetsPlugin(),
new CleanPlugin([path.join(__dirname, 'build', 'public')]),
new CompressionPlugin(),
// new BundleAnalyzerPlugin(),
],
module: {
rules: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
exclude: lazyRouteRegex,
use: [
{
loader: 'babel-loader',
},
],
},
{
test: lazyRouteRegex,
include: path.resolve(__dirname, 'src'),
use: [
{
loader: 'bundle-loader',
options: {
lazy: true,
},
},
{
loader: 'babel-loader',
},
],
},
{
test: /swiper.*\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: false,
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.s?css$/,
exclude: /swiper.*\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
},
},
{
loader: 'postcss-loader',
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.svg$/,
use: `svg-inline-loader?removeTags&removingTags[]=${['defs', 'style', 'title'].join(',removingTags[]=')}`,
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss', '.json'],
},
target: 'web',
};

bundle.js not found with webpack dev server

I'm having an issue with React/Redux/Webpack/Router.
Any "sub pages", such as: "/home/test", "users/registration" etc... fail to be loaded - and I get errors loading the "bundle.js" file generated by webpack.
The reason seems to be that the request to fetch the "bundle.js" is with the following url:
for path "/home/test": "/home/bundle.js"
for path "/users/registration": "/users/bundle.js"
Same issue occurs with the loading of "css" files and other resources.
This is my webpack configuration:
const { resolve } = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const config = {
devtool: 'cheap-module-eval-source-map',
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./main.js',
//'./assets/scss/main.scss',
],
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'dist'),
publicPath: '/',
},
context: resolve(__dirname, 'src'),
devServer: {
hot: true,
contentBase: resolve(__dirname, 'build'),
publicPath: '/',
historyApiFallback: true
},
module: {
rules: [
/* {
enforce: "pre",
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "eslint-loader"
}, */
{
test: /\.(js|jsx)$/,
loaders: [
'babel-loader',
],
exclude: /node_modules/,
},
{
test: /\.(scss|sass)$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
{
loader: 'sass-loader',
query: {
sourceMap: false,
},
},
],
publicPath: '../'
}),
},
{ test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=15000&name=images/[name].[ext]' },
{ test: /\.eot(\?v=\d+.\d+.\d+)?$/, use: 'file-loader?&name=fonts/[name].[ext]' },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'url-loader?limit=10000&mimetype=application/font-woff&name=fonts/[name].[ext]' },
{ test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, use: 'url-loader?limit=10000&mimetype=application/octet-stream&name=fonts/[name].[ext]' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: 'url-loader?limit=10000&mimetype=image/svg+xml&name=images/[name].[ext]' },
]
},
plugins: [
new webpack.LoaderOptionsPlugin({
test: /\.js$/,
options: {
eslint: {
configFile: resolve(__dirname, '.eslintrc'),
cache: false,
}
},
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new ExtractTextPlugin({ filename: './styles/style.css', disable: true, allChunks: true }),
new CopyWebpackPlugin([{ from: 'vendors', to: 'vendors' }]),
new OpenBrowserPlugin({ url: 'http://localhost:8080' }),
new webpack.HotModuleReplacementPlugin(),
],
};
module.exports = config;
It seems as if it always uses "../bundle.js" to find it for some reason.
Any help would be appreciated :)
Thank you,

How to use webpack HotModuleReplacementPlugin to build two html website

I use webpack HotModuleReplacementPlugin to let my website could hot reload when I fix the code.
But I don't know how to build two html page.
I want to build two page "index.html" & "introduction.html"
Now I use these code in my webpack.config.js but it will have a problem, in the Chrome dev tool would show
「Uncaught Error: _registerComponent(...): Target container is not a DOM element.」
How could I solved these problem?
var webpack = require('webpack');
var path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin');
var autoprefixer = require('autoprefixer');
var config = {
entry: {
index: [
'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/only-dev-server',
path.resolve(__dirname, 'src/index.jsx')
],
introduction: [
'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/only-dev-server',
path.resolve(__dirname, 'src/introduction.jsx')
],
},
output: {
path: path.resolve(__dirname, 'build'),
publishPath: '/',
filename: 'js/[name].js'
},
module: {
loaders: [
{
test:/\.jsx?$/,
exclude: /node_modules/,
loader: 'react-hot!babel'
},
{
test: /\.sass$/,
execlude: /node_modules/,
loader: 'style!css!postcss!sass'
},{
test: /\.scss$/,
execulde: /node_modules/,
loader: 'style!css!postcss!sass'
},
{
test: /\.css$/,
exclude: /node_modules/,
loader: 'style!css!postcss',
},
{
test: /\.(jpg|png|gif)$/,
exclude: /node_modules/,
loader: 'file?name=images/[name].[ext]'
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-woff'
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/octet-stream'
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file'
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=image/svg+xml'
}
]
},
postcss: [
autoprefixer({ browsers: ['last 2 versions']})
],
resolve: {
extensions: ['', '.js', '.jsx']
},
exclude: [
/(test)/
],
devServer: {
contenBase: './dist'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
filename: 'index.html',
template: './src/html/index.html'
}),
new htmlWebpackPlugin({
filename: 'introduction.html',
template: './src/html/introduction.html'
}),
]
}
module.exports = config;

Webpack - "css-loader/locals" miss matched for server.build and client.build

I setup a webpack config to build server.build and client.build, but they both producing different css/locals.
webpack.server.js
const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const serverConfig = {
name: 'server',
target: 'node',
externals: [nodeExternals()],
entry: [
__dirname+'/index.js'
],
output: {
path: path.join(__dirname, '/.build'),
filename: 'server.build.js',
publicPath: '.build/',
libraryTarget: 'commonjs2'
},
module: {
loaders: [
{
test:/\.(?:js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.(?:css|less)$/,
use: "css-loader/locals?import=1&modules=1&localIdentName=[name]__[local]__[hash:base64:7]",
exclude: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/,
loader: 'url-loader?limit=1000&name=./fonts/[name].[ext]?[hash:base64:5]#icomoon',
}
]
},
resolve: {
extensions: ['.jsx', '.js', '.json','.less']
}
};
module.exports = serverConfig;
webpack.client.js
const webpack = require('webpack');
const path = require('path');
const context = path.resolve(__dirname, 'src');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const config = {
name:"client",
context,
entry: __dirname+'/src/app.js',
output: {
path: __dirname+"/.build/assets",
filename: 'bundle.js'
},
devtool: "source-map",
module: {
rules: [
{
test:/\.(?:js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.(?:css|less)$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader?module',
options: {
sourceMap: true,
importLoader: true,
localIdentName:'[name]__[local]__[hash:base64:7]'
}
},
{
loader: 'less-loader',
options: {
sourceMap: true,
importLoader: true,
}
}
],
fallback: 'style-loader',
}),
exclude: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/,
loader: 'url-loader?limit=1000&name=./fonts/[name].[ext]?[hash:base64:5]#icomoon',
}
]
},
plugins: [
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true,
}),
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true),
NODE_ENV: JSON.stringify("production")
}
}),
],
resolve: {
extensions: ['.jsx', '.js', '.json']
}
};
module.exports = config;
Ex: server.build.js -> style__cont__2KTI-wF
bundle.js/bundle.css (client) -> style__cont__58B3ts_
I am really stuck at this point, i am new to react and there is no perfect approach to import css server side.

css modules object import returns empty

I am trying to use css modules inside react, but it is not working.
The log of this code:
import React from 'react'
import styles from '../../css/test.css'
class Test extends React.Component {
render() {
console.log(styles)
return (
<div className={styles.app}>
<p>This text will be blue</p>
</div>
);
}
}
export default Test
returns Object {}
and the rendered code are tags with no class:
<div><p>This text will be blue</p></div>
The css code is available at site, here is my test.css:
.test p {
color: blue;
}
If I changed the div to have class='test', the color of p changes to blue
Here is my webpack.config.js
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")
function _path(p) {
return path.join(__dirname, p);
}
module.exports = {
context: __dirname,
entry: [
'./assets/js/index'
],
output: {
path: path.resolve('./assets/bundles/'),
filename: '[name].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({
id: 'jsx',
threads: 4,
loaders: ["babel-loader"]
}),
new ExtractTextPlugin("[name].css", { allChunks: true })
],
module: {
loaders: [
{
test: /\.css$/,
include: path.resolve(__dirname, './assets/css/'),
loader: ExtractTextPlugin.extract("style-loader", "css-loader!resolve-url-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]")
},
{
test: /\.scss$/,
include: path.resolve(__dirname, './assets/css/'),
loader: ExtractTextPlugin.extract("style-loader", "css-loader!resolve-url-loader!sass-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]")
},
{
test: /\.jsx?$/,
include: path.resolve(__dirname, './assets/js/'),
exclude: /node_modules/,
loaders: ["happypack/loader?id=jsx"]
},
{
test: /\.png$/,
loader: 'file-loader',
query: {
name: '/static/img/[name].[ext]'
}
}
]
},
resolve: {
modulesDirectories: ['node_modules'],
extensions: ['', '.js', '.jsx'],
alias: {
'inputmask' : _path('node_modules/jquery-mask-plugin/dist/jquery.mask')
},
}
}
Can anyone help me?
Thanks in advance.
Looks like your passing the css-loader params to the resolve-url-loader:
"css-loader!resolve-url-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]"
Should be:
"css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]&importLoaders=1!resolve-url-loader"
A lot of time passed since this question, so my webpack was update many times with another technologies.
This webpack config is working:
...
module.exports = {
entry,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
devtool:
process.env.NODE_ENV === 'production' ? 'source-map' : 'inline-source-map',
module: {
rules: [
{
test: /\.jsx?$/,
include: path.resolve(__dirname, './app/view/'),
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.pcss$/,
include: path.resolve(__dirname, './app/view/'),
use: [
{
loader: 'style-loader'
},
{
loader:
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('postcss-import'),
require('postcss-mixins'),
require('postcss-cssnext')({
browsers: ['last 2 versions']
}),
require('postcss-nested'),
require('postcss-brand-colors')
];
}
}
}
],
exclude: /node_modules/
},
{
test: /\.(png|svg|jpg|webp)$/,
use: {
loader: 'file-loader'
}
}
]
},
resolve: {
extensions: ['.js', '.jsx'],
modules: [path.resolve(__dirname, 'node_modules')]
},
plugins
};
I guess that there is an issue with older versions at webpack with this line:
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
Try importLoaders and importLoader
You can see my repo too.
In my specific case, I'm using official utility facebook/create-react-app. You have to run the following command to get access to the webpack configuration:
npm run eject
You will then need to edit config/webpack.config.js and set the css-loader modules option to true.
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules:true <-----
}),

Resources