Universal Rendering with babel-plugin-webpack-loaders

Universal rendering is pretty cool. However, It is also a challenge to deal with miscellaneous require’s at server side. Dependent resource files, such as css or image resources could not be imported as rendering at server side by default. babel-plugin-webpack-loaders is a great plugin of babel. It uses the loader system of webpack to parse the resources correctly. Once you install it, you could configure the plugin in .babelrc or the register way to let babel know how to require these files other than javascript. The configuration is easy. First, you should provide a webpack configuration, the only necessary part is libraryTarget should be set to commonjs2 in the output part:

output: { libraryTarget: ‘commonjs2’ }

Then just set your webpack loaders as the usual ways:

 loaders: [ { 
test: /\.css$/,
loaders: [ ‘style-loader’, ‘css-loader’, ‘postcss-loader’, ]
} ]

the minimal configuration for a css-loader

You could bootstrap your babel by the setting in .babelrc. It makes sense to configure it in the register way:

require(‘babel-core/register’)({
“plugins”: [
[“babel-plugin-webpack-loaders”,
{ “config”: “./webpack.config.universal.js”, “verbose”: false }]
]})
//server start here
require('./my-express-server')

That’s it! anything should work fine now. Besides maybe you would like to bundle the resources with ExtratTextPlugin to generate the chunkhash filenames. You could also use assets-webpack-plugin to get the bundled filenames recorded in a specific json file:

{“main”:{“js”:”/static/main.2bcf7ddc93ada922416e.js”,”css”:”/static/main-79e081feef5d69b7eb56.css”}}

and access these filenames by just reading the asset file:

const assets = JSON.parse(fs.readFileSync(‘./build/assets.json’, ‘utf-8’))

Now you got these bundled filenames.