Is it possible to write webpack config in typescript?
Asked Answered
T

7

84

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

Tailpipe answered 16/10, 2016 at 20:46 Comment(3)
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.Rheotaxis
Hey! Would you care to consider moving the accept mark to the highly upvoted answer? It's the correct one.Sales
See webpack.js.org/configuration/configuration-languages/…Brunildabruning
B
88

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

Basketwork answered 14/12, 2016 at 7:40 Comment(7)
I should note that this is an undocumented feature, at least from the docs I saw up until nowBasketwork
ts-node seems to be the more popular choice: others have not been updated for yearsSpartacus
I use ts-node-dev (modified version of node-dev that uses ts-node under the hood), and it works great. (option for someone who wants ts-node to load the webpack.config.ts, but also wants webpack to restart when the config file -- or files imported by the config file -- change)Homogamy
How do you actually run web pack with webpack.config.ts (whats an example command). I dont see that anywhereSlovene
I don't see how this adds to the answer nor does it provide any means of running it.Absorb
As of today that source code link is 404. I guess that link wasn't to a particular commit. Obviously, there are risks when using undocumented features. Like others, I am still confused how to actually run webpack using ts-node, I've already had it installed but still get the same error.Jelks
@MarcH.Weiner it has been documented since 2017, and this is pointed out in this answer.Merryman
Z
43

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 (not needed in webpack 5+, as it already contains type definitions)
  • add type annotation comments to your webpack.config.js file, as such:

webpack.config.js:

// @ts-check

module.exports = /** @type { import('webpack').Configuration } */ ({
    ...
});
Zippy answered 2/5, 2019 at 14:19 Comment(0)
A
25

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.

Anarthria answered 21/4, 2021 at 16:19 Comment(6)
webpack is a disaster. This example doesn't work (although helpful) with webpack-dev-server.Desirable
Hey @ChrisHawkes, maybe this article helps you: dev.to/typescripttv/6-ways-to-configure-webpack-5a33Anarthria
It's totally possible to use Webpack Dev Server, this article will help you set it up: webpack.js.org/api/webpack-dev-serverPhenazine
test with webpack 5, "webpack --config webpack.config.ts" not working, but "webpack" worksBreastfeed
@Eric, where you able to find the solution to using --config with a webpack config written in typescript?Apure
my current working project, this is the script "build:only": "cls && yarn clear && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" NODE_ENV=production webpack --progress",Breastfeed
A
13

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

Alger answered 8/11, 2017 at 12:41 Comment(1)
When I tried doing this implementation, I got Namespace 'webpack' has no exported member 'NewLoaderRule' maybe you need to update this.Hettiehetty
L
3

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"
Lowestoft answered 12/5, 2020 at 9:15 Comment(0)
F
0

Make sure that you have installed ts-node package

Farhi answered 9/10, 2022 at 21:37 Comment(0)
B
-1

This is explained in Webpack's documentation:

To write the webpack configuration in TypeScript, you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the DefinitelyTyped project:

npm install --save-dev typescript `ts-node` @types/node @types/webpack
# and, if using webpack-dev-server < v4.7.0
npm install --save-dev @types/webpack-dev-server

and then proceed to write your configuration:

webpack.config.ts

import * as path from 'path';
import * as webpack from 'webpack';
// in case you run into any typescript error when configuring `devServer`
import 'webpack-dev-server';

const config: webpack.Configuration = {
  mode: 'production',
  entry: './foo.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'foo.bundle.js',
  },
};

export default config;

The above sample assumes version >= 2.7 or newer of TypeScript is used with the new esModuleInterop and allowSyntheticDefaultImports compiler options in your tsconfig.json file.

Note that you'll also need to check your tsconfig.json file. If the module in compilerOptions in tsconfig.json is commonjs, the setting is complete, else webpack will fail with an error. This occurs because ts-node does not support any module syntax other than commonjs.

There are three solutions to this issue:

  • Modify tsconfig.json.
  • Modify tsconfig.json and add settings for ts-node.
  • Install tsconfig-paths. The first option is to open your tsconfig.json file and look for compilerOptions. Set target to "ES5" and module to "CommonJS" (or completely remove the module option).

The second option is to add settings for ts-node:

You can keep "module": "ESNext" for tsc, and if you use webpack, or another build tool, set an override for ts-node. ts-node config

{
  "compilerOptions": {
    "module": "ESNext",
  },
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
}

The third option is to install the tsconfig-paths package:

npm install --save-dev tsconfig-paths

And create a separate TypeScript configuration specifically for your webpack configs:

tsconfig-for-webpack-config.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "esModuleInterop": true
  }
}

Tip
ts-node can resolve a tsconfig.json file using the environment variable provided by tsconfig-paths.

Then set the environment variable process.env.TS_NODE_PROJECT provided by tsconfig-paths like so:

package.json

{
  "scripts": {
    "build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack"
  }
}

Warning
We had been getting reports that TS_NODE_PROJECT might not work with "TS_NODE_PROJECT" unrecognized command error. Therefore running it with cross-env seems to fix the issue, for more info see this issue.

Brunildabruning answered 12/9, 2022 at 22:43 Comment(1)
Where is the run command? They give you 3 options on how to configure, but according to the docs only option 3 can be ran.Absorb

© 2022 - 2024 — McMap. All rights reserved.