Skip to content

Instantly share code, notes, and snippets.

@frenzzy
Last active April 8, 2021 11:13
Show Gist options
  • Save frenzzy/7e8433821057452e77f5429e73bf78a4 to your computer and use it in GitHub Desktop.
Save frenzzy/7e8433821057452e77f5429e73bf78a4 to your computer and use it in GitHub Desktop.
Code Splitting Example
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
import React from 'react';
import fetch from '../../core/fetch';
export const path = '/';
export const action = async (state) => {
const Home = await new Promise((resolve) => {
require.ensure([], (require) => resolve(require('./Home').default));
});
const response = await fetch('/graphql?query={news{title,link,contentSnippet}}');
const { data } = await response.json();
state.context.onSetTitle('React.js Starter Kit');
return <Home news={data.news} />;
};
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
import path from 'path';
import webpack from 'webpack';
import extend from 'extend';
import AssetsPlugin from 'assets-webpack-plugin';
const DEBUG = !process.argv.includes('--release');
const VERBOSE = process.argv.includes('--verbose');
const AUTOPREFIXER_BROWSERS = [
'Android 2.3',
'Android >= 4',
'Chrome >= 35',
'Firefox >= 31',
'Explorer >= 9',
'iOS >= 7',
'Opera >= 12',
'Safari >= 7.1',
];
const GLOBALS = {
'process.env.NODE_ENV': DEBUG ? '"development"' : '"production"',
__DEV__: DEBUG,
};
//
// Common configuration chunk to be used for both
// client-side (client.js) and server-side (server.js) bundles
// -----------------------------------------------------------------------------
const config = {
context: path.resolve(__dirname, '../src'),
output: {
path: path.resolve(__dirname, '../build/public/assets'),
publicPath: '/assets/',
sourcePrefix: ' ',
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, '../node_modules/react-routing/src'),
path.resolve(__dirname, '../src'),
],
query: {
// https://github.com/babel/babel-loader#options
cacheDirectory: DEBUG,
// https://babeljs.io/docs/usage/options/
babelrc: false,
presets: [
'react',
'es2015',
'stage-0',
],
plugins: [
'transform-runtime',
],
},
},
{
test: /\.scss$/,
loaders: [
'isomorphic-style-loader',
`css-loader?${JSON.stringify({
sourceMap: DEBUG,
// CSS Modules https://github.com/css-modules/css-modules
modules: true,
localIdentName: DEBUG ? '[name]_[local]_[hash:base64:3]' : '[hash:base64:4]',
// CSS Nano http://cssnano.co/options/
minimize: !DEBUG,
})}`,
'postcss-loader?parser=postcss-scss',
],
},
{
test: /\.json$/,
loader: 'json-loader',
},
{
test: /\.txt$/,
loader: 'raw-loader',
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
loader: 'url-loader',
query: {
name: DEBUG ? '[path][name].[ext]?[hash]' : '[hash].[ext]',
limit: 10000,
},
},
{
test: /\.(eot|ttf|wav|mp3)$/,
loader: 'file-loader',
query: {
name: DEBUG ? '[path][name].[ext]?[hash]' : '[hash].[ext]',
},
},
{
test: /\.jade$/,
loader: 'jade-loader',
},
],
},
resolve: {
root: path.resolve(__dirname, '../src'),
modulesDirectories: ['node_modules'],
extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', '.json'],
},
cache: DEBUG,
debug: DEBUG,
stats: {
colors: true,
reasons: DEBUG,
hash: VERBOSE,
version: VERBOSE,
timings: true,
chunks: VERBOSE,
chunkModules: VERBOSE,
cached: VERBOSE,
cachedAssets: VERBOSE,
},
postcss(bundler) {
return [
require('postcss-import')({ addDependencyTo: bundler }),
require('precss')(),
require('autoprefixer')({ browsers: AUTOPREFIXER_BROWSERS }),
];
},
};
//
// Configuration for the client-side bundle (client.js)
// -----------------------------------------------------------------------------
const clientConfig = extend(true, {}, config, {
entry: './client.js',
output: {
filename: DEBUG ? '[name].js?[chunkhash]' : '[name].[chunkhash].js',
chunkFilename: DEBUG ? '[name].[id].js?[chunkhash]' : '[name].[id].[chunkhash].js',
},
target: 'web',
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({ ...GLOBALS, 'process.env.BROWSER': true }),
// Emit a file with assets paths
// https://github.com/sporto/assets-webpack-plugin#options
new AssetsPlugin({
path: path.resolve(__dirname, '../build'),
filename: 'assets.js',
processOutput: x => `module.exports = ${JSON.stringify(x)};`,
}),
// Assign the module and chunk ids by occurrence count
// Consistent ordering of modules required if using any hashing ([hash] or [chunkhash])
// https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin
new webpack.optimize.OccurenceOrderPlugin(true),
...(DEBUG ? [] : [
// Search for equal or similar files and deduplicate them in the output
// https://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
new webpack.optimize.DedupePlugin(),
// Minimize all JavaScript output of chunks
// https://github.com/mishoo/UglifyJS2#compressor-options
new webpack.optimize.UglifyJsPlugin({
compress: {
screw_ie8: true, // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
warnings: VERBOSE,
},
}),
// A plugin for a more aggressive chunk merging strategy
// https://webpack.github.io/docs/list-of-plugins.html#aggressivemergingplugin
new webpack.optimize.AggressiveMergingPlugin(),
]),
],
// Choose a developer tool to enhance debugging
// http://webpack.github.io/docs/configuration.html#devtool
devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
});
//
// Configuration for the server-side bundle (server.js)
// -----------------------------------------------------------------------------
const serverConfig = extend(true, {}, config, {
entry: './server.js',
output: {
filename: '../../server.js',
libraryTarget: 'commonjs2',
},
target: 'node',
externals: [
/^\.\/assets$/,
function filter(context, request, cb) {
const isExternal =
request.match(/^[@a-z][a-z\/\.\-0-9]*$/i) &&
!request.match(/^react-routing/) &&
!context.match(/[\\/]react-routing/);
cb(null, Boolean(isExternal));
},
],
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({ ...GLOBALS, 'process.env.BROWSER': false }),
// Adds a banner to the top of each generated chunk
// https://webpack.github.io/docs/list-of-plugins.html#bannerplugin
new webpack.BannerPlugin('require("source-map-support").install();',
{ raw: true, entryOnly: false }),
// Do not create separate chunks of the server bundle
// https://webpack.github.io/docs/list-of-plugins.html#limitchunkcountplugin
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
],
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
devtool: 'source-map',
});
export default [clientConfig, serverConfig];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment