ericclemmons/start-server-webpack-plugin

Can it support typescript

kaimiyang opened this issue · 11 comments

I use typescript and find 'start-server-webpack-plugin' is good in development environment. but ...
when I upgrade typescript, it's TSError

TSError: ⨯ Unable to compile TypeScript:
config/WebpackDev.ts(5,31): error TS7016: Could not find a declaration file for module 'start-server-webpack-plugin'. '/Users/yangkang/work/nodejs/proj/node_modules/start-server-webpack-plugin/dist/StartServerPlugin.js' implicitly has an 'any' type.
  Try `npm install @types/start-server-webpack-plugin` if it exists or add a new declaration (.d.ts) file containing `declare module 'start-server-webpack-plugin';`

even I declare start-server-webpack-plugin.d.ts, please help, support typescript:
"typescript": "^2.9.2",

I'm using it with Typescript.

Here is my webpack config:

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const StartServerPlugin = require('start-server-webpack-plugin');

module.exports = {
	entry: ['webpack/hot/poll?1000', './server/index.ts'],
	watch: true,
	mode: 'development',
	devtool: 'inline-source-map',
	target: 'node',
	node: {
		__filename: true,
		__dirname: true
	},
	resolve: {
		extensions: ['.ts', '.js']
	},
	externals: [nodeExternals({ whitelist: ['webpack/hot/poll?1000'] })],
	module: {
		rules: [
			{
				test: /\.[tj]s$/,
				use: [
					{
						loader: 'awesome-typescript-loader'
					}
				],
				exclude: /node_modules/
			}
		]
	},
	plugins: [
		new StartServerPlugin({
			name: 'server.js',
			nodeArgs: [`--require`, 'dotenv/config', '--inspect-brk=9229']
		}),
		new webpack.NamedModulesPlugin(),
		new webpack.HotModuleReplacementPlugin(),
		new webpack.NoEmitOnErrorsPlugin(),
		new webpack.BannerPlugin({
			banner: 'require("source-map-support").install();',
			raw: true,
			entryOnly: false
		})
	],
	output: { path: path.join(__dirname, 'dist'), filename: 'server.js' }
};

Make sure to install the typings for the webpack environment @types/webpack-env or you might have issues with module.hot

I hope it helps.

Oh...

Are you using Typescript in your webpack config?

Yes, I want to use ts in my program, but encounter many questions. one of these is 'Hot Module Replacement'

When the webpack configuration is written in typescript, the declaration file .d.ts is missing.

I created one from this TypeScript guideline.
I tried to list the type of all the options, but I might have missed some.

// Type definitions for start-server-webpack-plugin 2.2
// Project: https://github.com/ericclemmons/start-server-webpack-plugin
// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
// Typescript Version: 3.8

import { Plugin, Compiler } from 'webpack'

export = StartServerWebpackPlugin;

declare class StartServerWebpackPlugin extends Plugin {
    constructor(name?: string);
    constructor(options?: StartServerWebpackPlugin.Options);

    apply(compiler: Compiler): void;
}

declare namespace StartServerWebpackPlugin {
    export interface Options {
        /**
         * Name of the server to start (built asset from webpack).
         * If not provided, the plugin will tell you the available names.
         */
        name?: string;
        /**
         * Arguments for node.
         * Default: `[]`.
         */
        nodeArgs?: string[];
        /**
         * Arguments for the script.
         * Default: `[]`.
         */
        args?: string[];
        /**
         * Signal to send for HMR.
         * Default: 'false'.
         */
        signal?: boolean;
        /**
         * Allow typing 'rs' to restart the server.
         * Default: 'true' if in 'development' mode, 'false' otherwise.
         */
        keyboard?: boolean;
    }
}

You can name it start-server-webpack-plugin.d.ts at the root of your project.

But the best would be to have this file at the root of this project, under the name index.d.ts.
It would then be supported by webpack configurations in typescript.


Also, I'm currently running on Windows and I have the same issue as in #23.
So, I cannot use the signal option, but otherwise it's running well.

@AGenson we're currently close to releasing v3, check out #38. Does that branch work for you?

Do you mean fivethreeo:webpack5-use-the-fork?

I tried to run this branch (#38) with my code.
Just to clarify, I should remove webpack/hot from entry and nodeExternals, right?

I found several issues:

  • The verbose is unreadable. I would maybe put it to false by default.
  • I was naming my output index.dev.js, but there is no way to make it work with entryName. I did not have that issue before. Though, there is no problem if I let the default entryName and let webpack name the output. It seems to be a coding issue:
StartServerPlugin.js:113
      throw new Error(`Requested entry "${entryName}" does not exist, try one of: ${(entrypoints.keys ? entrypoints.keys() : Object.keys(entrypoints)).join(' ')}`);
                                                                                                                                                       ^        
TypeError: (intermediate value)(intermediate value)(intermediate value).join is not a function
    at StartServerPlugin._getScript
  • The restart of the server seems to happen only once every two restarts.
    But it seems to have been pointed out in #30 already.
  • Finally, the signal option still does not work for me:
TypeError [ERR_UNKNOWN_SIGNAL]: Unknown signal: SIGUSR2
    at process.kill (internal/process/per_thread.js:193:15)
    at StartServerPlugin._hmrWorker

I also had to add index.d.ts at the root of fivethreeo:webpack5-use-the-fork to make it work with my webpack configuration in typescript.

// Type definitions for start-server-webpack-plugin 3.0
// Project: https://github.com/ericclemmons/start-server-webpack-plugin
// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
// Typescript Version: 3.8

import { Plugin, Compiler } from 'webpack'

export = StartServerWebpackPlugin;

declare class StartServerWebpackPlugin extends Plugin {
    constructor(entryName?: string);
    constructor(options?: StartServerWebpackPlugin.Options);

    apply(compiler: Compiler): void;
}

declare namespace StartServerWebpackPlugin {
    export interface Options {
        /**
         * Whether to print logs or not.
         * Default: `true`.
         */
        verbose?: boolean;
        /**
         * Name of the server to run (built asset from webpack).
         * Default: `'main'`
         */
        entryName?: string;
        /**
         * Run once and exit when worker exits.
         * Default: `false`.
         */
        once?: boolean;
        /**
         * Arguments for node.
         * Default: `[]`.
         */
        nodeArgs?: string[];
        /**
         * Arguments for the script.
         * Default: `[]`.
         */
        scriptArgs?: string[];
        /**
         * Signal to send for HMR.
         * Default: `false`.
         */
        signal?: boolean;
        /**
         * Allow typing 'rs' to restart the server.
         * Default: 'true' if in 'development' mode, 'false' otherwise.
         */
        restartable?: boolean;
    }
}
  • signal for sure won't work on windows, but you should be able to leave it off and then it will poll
  • can you debug the entryName, can you find the correct entry somewhere in the compiler results?
  • yes I agree that verbose should be off by default, but didn't get around to fully coding that up
  • thanks for the typing, i'll include that or you can make a PR so you get attributed.

Yes, it still works without signal.

Regarding the entryName, I'm not sure to understand what it represents.
When debugging, I found out that it would work by naming my output index.dev.js and letting the default entryName to 'main'. It seems that the entryName is the name of chunk?


I dig a little bit more into type declaration (I'm still new to the whole TypeScript world).
From their guidelines, they recommend having the declaration file in the project only if the project itself is written in TypeScript. Otherwise, it should be published to the @types organisation on npm.

So I took the initiative to implement it and create a PR on DefinitelyTyped.
The PR is under review before getting published.

One issue is, their way of publishing is linked to the current version of a package. So the type declaration is for v2.2 and not v3. But it can be updated later.

It would be great if you could review it, as you have a better understanding of the code it is relating to.
I tried to put the types of all the options and main methods, but I might have missed or misunderstood some of them. Here's the link: Pull-Request 43689

In addition to the declaration file, I needed to implement a test, so I looked up to the implementation from other plugins:

The typing has just been published, it can now be added via yarn/npm:

yarn add -D @types/start-server-webpack-plugin

The typing will need an update once you release v3.

@AGenson @wmertens @kaimiyang I have created an analog to this plugin, which works properly with webpack 5 and supports typescript from scratch (no need to install package with types)
https://github.com/atassis/run-script-webpack-plugin