This guide stems from theGetting Started guide.
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack.
First install the TypeScript compiler and loader by running:
npminstall --save-dev typescript ts-loaderNow we'll modify the directory structure & the configuration files:
project
webpack-demo |- package.json |- package-lock.json+ |- tsconfig.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src |- index.js+ |- index.ts |- /node_modulestsconfig.json
Let's set up a configuration to support JSX and compile TypeScript down to ES5...
{"compilerOptions":{"outDir":"./dist/","noImplicitAny":true,"module":"es6","target":"es5","jsx":"react","allowJs":true,"moduleResolution":"node"}}SeeTypeScript's documentation to learn more abouttsconfig.json configuration options.
To learn more about webpack configuration, see theconfiguration concepts.
Now let's configure webpack to handle TypeScript:
webpack.config.js
const path=require('path');module.exports={ entry:'./src/index.ts', module:{ rules:[{ test:/\.tsx?$/, use:'ts-loader', exclude:/node_modules/,},],}, resolve:{ extensions:['.tsx','.ts','.js'],}, output:{ filename:'bundle.js', path: path.resolve(__dirname,'dist'),},};This will direct webpack toenter through./index.ts,load all.ts and.tsx files through thets-loader, andoutput abundle.js file in our current directory.
Now lets change the import oflodash in our./index.ts due to the fact that there is no default export present inlodash definitions.
./index.ts
- import _ from 'lodash';+ import * as _ from 'lodash'; function component() { const element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component());To make imports do this by default and keepimport _ from 'lodash'; syntax in TypeScript, set"allowSyntheticDefaultImports" : true and"esModuleInterop" : true in yourtsconfig.json file. This is related to TypeScript configuration and mentioned in our guide only for your information.
webpack.config.tsThere are 5 ways to use TypeScript inwebpack.config.ts:
Using webpack with TypeScript config:
webpack -c ./webpack.config.ts(Not all things are supported due to limitations ofrechoir andinterpret.)
Using custom--import for Node.js:
NODE_OPTIONS='--import tsx' webpack --disable-interpret -c ./webpack.config.tsUsing built-in TypeScript module for Node.js v22.7.0 ≥ YOUR NODE.JS VERSION < v23.6.0:
NODE_OPTIONS='--experimental-strip-types' webpack --disable-interpret -c ./webpack.config.tsUsing built-in TypeScript module for Node.js ≥ v22.6.0:
webpack --disable-interpret -c ./webpack.config.tsUsing a tsx for Node.js ≥ v22.6.0:
NODE_OPTIONS='--no-experimental-strip-types --import tsx' webpack --disable-interpret -c ./webpack.config.tsWe usets-loader in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier.
ts-loader usestsc, the TypeScript compiler, and relies on yourtsconfig.json configuration. Make sure to avoid settingmodule to "CommonJS", or webpack won't be able totree-shake your code.
Note that if you're already usingbabel-loader to transpile your code, you can use@babel/preset-typescript and let Babel handle both your JavaScript and TypeScript files instead of using an additional loader. Keep in mind that, contrary tots-loader, the underlying@babel/plugin-transform-typescript plugin does not perform any type checking.
To learn more about source maps, see thedevelopment guide.
To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration:
tsconfig.json
{ "compilerOptions": { "outDir": "./dist/",+ "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es5", "jsx": "react", "allowJs": true, "moduleResolution": "node", } }Now we need to tell webpack to extract these source maps and include in our final bundle:
webpack.config.js
const path = require('path'); module.exports = { entry: './src/index.ts',+ devtool: 'inline-source-map', module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/, }, ], }, resolve: { extensions: [ '.tsx', '.ts', '.js' ], }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, };See thedevtool documentation for more information.
It's possible to use webpack specific features in your TypeScript code, such asimport.meta.webpack. And webpack provides types for them as well, add a TypeScriptreference directive to declare it:
/// <reference types="webpack/module" />console.log(import.meta.webpack);// without reference declared above, TypeScript will throw an errorWhen installing third party libraries from npm, it is important to remember to install the typing definition for that library.
For example, if we want to install lodash we can run the following command to get the typings for it:
npminstall --save-dev @types/lodashIf the npm package already includes its declaration typings in the package bundle, downloading the corresponding@types package is not needed. For more information see theTypeScript changelog blog.
To use non-code assets with TypeScript, we need to defer the type for these imports. This requires acustom.d.ts file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for.svg files:
custom.d.ts
declaremodule'*.svg'{const content:any;exportdefault content;}Here we declare a new module for SVGs by specifying any import that ends in.svg and defining the module'scontent asany. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more.
This may degrade build performance.
See theBuild Performance guide on build tooling.