Is it possible to write webpack config in typescript?

TypescriptWebpack

Typescript Problem Overview


I saw, when searching, that there are typings for webpack. So it seems I can write webpack.config.js in typescript? But how can I do that?

enter image description here

Typescript Solutions


Solution 1 - Typescript

You can use TS as your config file (webpack.config.ts)

There is a clear clue for that, see Source Code

The ** interpret** module used there is a list of extension files and their loaders.

In the highlighted code webpack generates an array of all possible extension for the default files.

For example, give webpack.config you will get an array with

  • webpack.config.ts
  • webpack.config.js
  • ...... and so on

For this to work you need to install one of the packages that support loading your extension.

For example, TS has some node packages that enable you to require('something.ts') and the package will do the work.

The interpret package states that one of these packages is required

> ts-node, typescript-node, typescript-register, typescript-require

So npm/yarn ts-node then just put a webpack.config.ts file and it will just work!

EDIT: Webpack documentation now has dedicated section on configuration languages which includes TypeScript, CoffeeScript and Babel & JSX

Solution 2 - Typescript

If you are using vscode as editor (or maybe others which support the JSDoc typing syntax) and you're only interested in typechecking your file to guide completion on your configuration object, you can do it like so:

In vscode you can do this as such:

  • npm i -D @types/webpack
  • add type annotation comments to your webpack.config.js file, as such:

webpack.config.js:

// @ts-check

module.exports = /** @type { import('webpack').Configuration } */ ({
    ...
});

Solution 3 - Typescript

Webpack 4

When using webpack v4, you have to install typings for webpack (npm install --save @types/webpack).

Webpack 5

When using webpack v5, you don't need to install external typings because webpack 5 already ships with TypeScript definitions. It's actually recommended to remove @types/webpack when you have them installed: https://webpack.js.org/blog/2020-10-10-webpack-5-release/#typescript-typings

Webpack Configuration

Here is an example of a webpack config written purely in TypeScript (that's why it's file name also ends on .ts):

webpack.config.ts

import {Configuration} from 'webpack';

const config: Configuration = {
  mode: 'development',
  module: {
    rules: [
      {
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        test: /\.[tj]sx?$/,
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  },
};

export default config;

Documentation

If you are interested in all the possibilities of how to configure webpack, then the 6 ways to configure Webpack article may help you.

Solution 4 - Typescript

I wrote a blog post titled "Writing your Webpack Configuration in TypeScript" for full details, here is the TLDR:

The accepted answer didn't work for me, I also found that the ts-node dependency didn't support ES6 import statements.

The simplest method I've found is to simply run the TypeScript tsc tool to convert your TypeScript to JavaScript, then run the webpack tool as normal:

tsc --lib es6 webpack.config.ts
webpack --config webpack.config.js

This has the added advantage of not requiring you to install any dependencies, as in the other answer.

Bonus Top Tip

The Webpack types are a mixture of Webpack 1 & 2 syntax. You can use TypeScript to ensure that you are only using Webpack 2 syntax and remove all types from the Webpack 1 syntax. I did this by creating some new types extending the Webpack types:

// webpack.common.ts
import * as webpack from "webpack";

export type INewLoader = string | webpack.NewLoader;
export interface INewUseRule extends webpack.NewUseRule {
  use: INewLoader[];
}
export interface INewLoaderRule extends webpack.NewLoaderRule {
  loader: INewLoader;
}
export type INewRule = INewLoaderRule | INewUseRule |
    webpack.RulesRule | webpack.OneOfRule;
export interface INewModule extends webpack.NewModule {
  rules: INewRule[];
}
export interface INewConfiguration extends webpack.Configuration {
  module?: INewModule;
}
export interface IArguments {
  prod: boolean;
}
export type INewConfigurationBuilder = (env: IArguments) => INewConfiguration;

You can then use these types in your Webpack configuration:

import * as path from "path";
import * as webpack from "webpack";
import { INewConfiguration, INewConfigurationBuilder } from "./webpack.common";

const configuration: INewConfiguration = {
  // ...
};
export default configuration;

Or you can pass arguments to your webpack configuration file like so:

import * as path from "path";
import * as webpack from "webpack";
import { IArguments, INewConfiguration, INewConfigurationBuilder } from "./webpack.common";

const configurationBuilder: INewConfigurationBuilder = 
  (env: IArguments): INewConfiguration => {
    const isDevBuild = !(env && env.prod);
    const configuration: INewConfiguration = {
      // ...
    };
    return configuration;
  };
export default configurationBuilder;

You can pass arguments to webpack like this:

> webpack --env.prod

Solution 5 - Typescript

If you do not want to transpile your webpack config and then pass it to webpack script in two steps I came up with other solution. Using webpack programmatically is really easy, so I have created a build script build.ts

import webpack from 'webpack'

import config from './webpack.config'

webpack(config, (err, stats) => err 
    ? console.log(err) 
    : console.log(stats)
);

Then you may run npm script with ts-node like so

"build": "ts-node --project ./path-to/tsconfig.json ./build.ts"

Solution 6 - Typescript

I can't find any clue in the webpack sourcecode, that you can use a webpack.config.ts file directly as configuration for your project.

Of course, because TypeScript is just a superset for Javascript, you can always use TypeScript to write your webpack.config.ts and convert it to a valid Javascript webpack.config.js file.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstarcornView Question on Stackoverflow
Solution 1 - TypescriptShlomi AssafView Answer on Stackoverflow
Solution 2 - TypescriptpqnetView Answer on Stackoverflow
Solution 3 - TypescriptBenny NeugebauerView Answer on Stackoverflow
Solution 4 - TypescriptMuhammad Rehan SaeedView Answer on Stackoverflow
Solution 5 - TypescriptDamian PaszkowskiView Answer on Stackoverflow
Solution 6 - TypescriptmichelgottaView Answer on Stackoverflow