TypeScript 2.1, npm, and webpack 2
Update 11-Mar-2017: I put a little skeleton repo up at https://github.com/overthink/tstemplate
Each time I want to start a new project with TypeScript and npm I find that I’ve forgotten how to do it. This article is my personal reminder.
Approach
- Prefer as little boilerplate as possible
- Use aggressive TypeScript settings for typechecking
- Don’t rely on anything installed globally (except npm)
- i.e.
npm install
is the only command you need to get a get a freshly cloned repo working
- i.e.
- fewer tools is better than more tools
- i.e. npm (commands) for automation and dependencies (no grunt, no typings, no bower, etc)
- webpack for bundling
- As a working example, assume D3 and
immutable.js as example external
dependencies (i.e. loaded via
<script>
tags in the HTML, not bundled by webpack)- See “externals” section of
webpack.config.js
below for more
- See “externals” section of
I don’t know if this is good or “cool”, but it has been working for me and seems relatively small and understandable.
How
mkdir myproj
cd myproj
mkdir src dist
npm init # (use `./dist/bundle.js` as entry point)
npm install --save d3 immutable
npm install --save-dev typescript@2 webpack@2 ts-loader source-map-loader \
webpack-dev-server@2 @types/d3 @types/immutable
echo "console.log('hello world');" > src/index.ts
git init
The @types
stuff loads type definitions from
DefinitelyTyped.
There have been other ways to do this in the past, but this appears to be the
TypeScript 2.x+ “best” way.
Files to add to project root
.gitignore
This will vary a lot by user. I use IDEA (commercial) and alm (free!) for TypeScript, and thus exclude their project files.
*.iml
.idea
.alm
dist
node_modules
.editorconfig
Optional. See http://editorconfig.org/
[*.{js,jsx,ts,tsx}]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = true
insert_final_newline = true
tsconfig.json
Create a
tsconfig.json
in the project root. This will vary a lot by project, but it’s a starting
point.
{
"compilerOptions": {
"strictNullChecks": true,
"noImplicitAny": true,
"outDir": "./dist/",
"sourceMap": true,
"target": "es5"
},
"filesGlob": [
"./src/*.ts"
]
}
webpack.config.js
Create webpack.config.js
in the project root. Something like:
const path = require("path");
module.exports = {
entry: "./src/index.ts",
output: {
filename: "./dist/bundle.js"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' as resolvable extensions.
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
},
{
test: /\.ts$/,
use: ["ts-loader"]
}
]
},
devServer: {
contentBase: path.join(__dirname, "/dist"),
compress: true,
port: 8000
},
// Omit "externals" if you don't have any. Just an example because it's
// common to have them.
externals: [
// Don't bundle giant dependencies, instead assume they're available in
// the html doc as global variables node module name -> JS global
// through which it is available
{"d3": "d3",
"immutable": "Immutable"}
]
};
package.json
Add npm script section
i.e. npm run
commands for automation.
Add this to package.json
. The only semi-interesting thing here is that I’m
not relying on globally installed webpack.
// add to package.json
"scripts": {
"start": "node_modules/.bin/webpack-dev-server",
"build": "node_modules/.bin/webpack",
"build:watch": "node_modules/.bin/webpack -w",
"clean": "rm ./dist/*"
},
References
- A very elaborate typescript+webpack skeleton
- WTF is webpack, really
- My old pixi.js article - similar, more complicated, and out of date