putting the "meth" in "programming methodology"
Suppose you’re building a web application using React/Typescript/Webpack (for example, maybe you work at Distribute). You recognize that you need caching and cache busters. You follow guides such as this, this, this, this (and some others I forgot), and because it works with regular JSX, you might end up with something like this:
// vendor.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
// app.tsx
import * as React from "react"
import * as ReactDOM from "react-dom"
ReactDOM.render(
<h1>shit was so cache</h1>,
document.getElementById("root")
)
// webpack.config.js
const path = require('path')
const webpack = require('webpack')
const WebpackMd5Hash = require('webpack-md5-hash')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin')
const config = {
entry: {
vendor: './src/vendor.tsx',
main: './src/app.tsx'
},
output: {
path: path.join(__dirname, '/public'),
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].js'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json']
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity
}),
new WebpackMd5Hash(),
new InlineManifestWebpackPlugin({
name: 'webpackManifest'
}),
new HtmlWebpackPlugin({
template: './src/index.ejs'
})
],
module: {
rules: [{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader'
}]
}
}
module.exports = [config]
But then when you try to build it
Hash: 0c0c96c0c8f921c2e280
Version: webpack 3.0.0
Child
Hash: 0c0c96c0c8f921c2e280
Time: 2259ms
Asset Size Chunks Chunk Names
main.869bbf8c0a14609301a3.js 746 kB 0 [emitted] [big] main
vendor.24563705cc4bb54fccd8.js 6.14 kB 1 [emitted] vendor
index.html 289 bytes [emitted]
[81] ./src/vendor.tsx 79 bytes {1} [built]
[82] ./src/app.tsx 257 bytes {0} [built]
+ 183 hidden modules
Child html-webpack-plugin for "index.html":
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 581 bytes {0} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ 1 hidden module
You get a gigantic main
bundle with everything. And an empty
vendor
bundle. Fuck.
Export your vendor modules:
// vendor.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
export { React, ReactDOM }
And then:
Hash: 484954d50613815c9110
Version: webpack 3.0.0
Child
Hash: 484954d50613815c9110
Time: 2279ms
Asset Size Chunks Chunk Names
main.c6ed251878b712466ff9.js 377 bytes 0 [emitted] main
vendor.9d1f36768857c94e8503.js 752 kB 1 [emitted] [big] vendor
index.html 289 bytes [emitted]
[83] ./src/vendor.tsx 206 bytes {1} [built]
[184] ./src/app.tsx 257 bytes {0} [built]
+ 183 hidden modules
Child html-webpack-plugin for "index.html":
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 581 bytes {0} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ 1 hidden module
Hell yeah.
Maybe this is obvious to real frontend engineers who understand Webpack/React/ES6/Typescript intimately, but I’m a backend guy, and I couldn’t look up the answer. But now you can. It’s all about Giving Back To The People
The Rest is Up to You…