Original address: marxjiao.com/2018/04/10/…
Learning Node.js, here is how to build a typescript-based Node development environment using WebPack.
Essential functionality for the entire environment
A good development environment allows developers to focus on the code and not on anything else. Here are some of the necessary conditions.
- A single command can start the project.
- A command can package items.
- Code changes can be updated automatically at development time, preferably hot, rather than restarting the service, in preparation for later debugging with front-end code.
- You can debug using an editor or chrome. I’m used to vscode.
Basic Construction idea
Use TS globally, including scripts, webpack configuration files. NPM is used to call the TS script, which is executed using TS-Node, and the TS script is used to call the WEBpack API to package the build file.
npm scipts -> start-dev.ts -> webpack(webpackConfig)
Here’s why you use TS scripts to call webpack instead of writing webpack commands directly in NPM scripts. My idea is All In Typescrpt, try to use TS instead of JS, and use the Node API of Webpack to easily write webPack configuration In TS. Another advantage of this approach is that the webPack configuration can be written dynamically, generating the desired configuration based on the parameters passed in.
The selection
So far the selection of the project has been very clear.
-
Typescript
The main language used by the project adds enhanced type support for front-end development and can avoid many problems in the coding process. -
Koa
It is widely used. No additional functionality, middleware plug and play. -
Webpack
Package tools, hot loading in development. -
ts-node
Used to execute ts scripts directly. -
start-server-webpack-plugin
The key webpack plugin can launch the service directly after compilation, and supports hot loading in Signal modewebpack/hot/signal
Very good.
Environment set up
Let’s start by writing a simple Web server in Koa and then build the environment for that server.
Project code
Create a new server/app.ts file. This file is used to create a KOA app.
import * as Koa from 'koa';
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello World';
});
export default app;
Copy the code
We need another file to start the server and listen for server/app.ts changes to hot load the project.
The new server/server. Ts
import * as http from 'http'; import app from './app'; // app.callback() returns a function that creates a server through http.createserver, similar to Express and connect. let currentApp = app.callback(); Const server = http.createserver (currentApp); server.listen(3000); / / heat load if (module. Hot) {/ / listen/app. Ts module. Hot. Accept ('. / app. Ts' () = > {/ / if there is a change, RemoveListener ('request', currentApp); currentApp = app.callback(); server.on('request', currentApp); }); }Copy the code
Compile the configuration
Before writing the WebPack configuration, let’s write down the TS configuration and the Babel configuration.
Typescript configuration
This is the configuration that webPack uses to compile code, and the configuration that TS-Node uses to run scripts will be described later. Let’s create config/tsconfig.json:
"Module ": "es2015", "noImplicitAny": true, "sourceMap": true, "moduleResolution": "node", "isolatedModules": true, "target": "es5", "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "inlineSources": false, "lib": ["es2015"] }, "exclude": [ "node_modules", "**/*.spec.ts" ] }Copy the code
Babel configuration
Babelrc, “modules”: false is important, tree shaking, HMR depends on it.
{
"presets": [["env", {"modules": false}]]
}
Copy the code
Webpack configuration
Typically, you need to prepare two webPack configurations, one for development and one for distribution. As mentioned earlier, packaging using the WebPack API makes it possible to create webPack configurations on the fly. So here we write a WebpackConfig class that generates the configuration of different environments based on the parameters when creating the instance.
The difference between development and release environments
First of all, the modes of the two environments are different. The development environment is Development, while the release environment is production. More information about mode can be found in the Webpack documentation.
The development environment requires hot loading and startup services. The entry needs to be configured with ‘webpack/hot/ Signal ‘. Use webpack-node-externals to package ‘webpack/hot/ Signal ‘into the code. Add HotModuleReplacementPlugin, use the start – server – webpack – the plugin to start the service and open the heat load.
Webpack configuration content
Now let’s write down the WebPack configuration. The key points are in the comments.
Create a new file config/ webpack.config.ts.
import * as path from 'path'; import * as StartServerPlugin from "start-server-webpack-plugin"; import * as webpack from 'webpack'; import * as nodeExternals from 'webpack-node-externals'; import {Configuration, ExternalsElement} from 'webpack'; Class WebpackConfig implements Configuration {// Node environment target: Configuration['target'] = "node"; Mode: Configuration['mode'] = 'production'; // Entry = [path.resolve(__dirname, '../server/server.ts')]; output = { path: path.resolve(__dirname, '.. /dist'), filename: "server.js" }; Externals: ExternalsElement[] = []; // loader module = {rules: [{test: /\.tsx?$/, use: [// TSC: Babel {loader: 'babel-loader',}, {loader: 'ts-loader', options: {// Speed up transpileOnly: true, // Specify a specific TS compilation configuration to distinguish the script's TS configuration configFile: path.resolve(__dirname, './tsconfig.json') } } ], exclude: /node_modules/ }, { test: /\.jsx?$/, use: 'babel-loader', exclude: /node_modules/ } ] }; resolve = { extensions: [".ts", ".js", ".json"], }; / / development environment also use NoEmitOnErrorsPlugin plugins = [new webpack. NoEmitOnErrorsPlugin ()]; Constructor (mode: Configuration['mode']) {constructor(mode: Configuration['mode']) { this.mode = mode; If (mode === 'development') {// Add webpack/hot/signal to update this.entry.push('webpack/hot/signal'); This.externals. push(// add webpack/hot/signal to externals ({whitelist: ['webpack/hot/signal']})); Const devPlugins = [/ / used to hot update new webpack HotModuleReplacementPlugin (), / / start the service new StartServerPlugin ({/ / start the file name: NodeArgs: ['--inspect']}),] this.plugins.push(... devPlugins); } } } export default WebpackConfig;Copy the code
Compile the script
Using TS-Node to launch the script requires the new tsconfig.json, which is compiled to run in Node.
Create tsconfig.json in the project root directory:
{"compilerOptions": {// For node environment to run directly "module": "commonjs", "noImplicitAny": true, "sourceMap": true, "moduleResolution": "node", "isolatedModules": true, "target": "es5", "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "inlineSources": false, "lib": ["es2015"] }, "exclude": [ "node_modules", "**/*.spec.ts" ] }Copy the code
To develop the script
Start the development script, scripts/start-dev.ts:
import * as webpack from 'webpack'; import WebpackConfig from '.. /config/Webpack.config'; Const devConfig = new WebpackConfig('development'); Watch ({aggregateTimeout: 300}, (err: Error) => {console.log(err); });Copy the code
Add it in package.json
"scripts": {
"dev": "rm -rf ./dist && ts-node ./scripts/start-dev.ts"
},
Copy the code
After executing yarn dev, we can see that the project is started:
Command line output
Browser display:
Browser display
Modify server/app. Ts
import * as Koa from 'koa';
const app = new Koa();
app.use(ctx => {
- ctx.body = 'Hello World';
+ ctx.body = 'Hello Marx';
});
export default app;
Copy the code
You can see the command line output:
Command line output after updating code
Refresh the browser:
Browser display
You can see that the hot update has taken effect.
Publish the package script
New package script scripts/build.ts:
import * as webpack from 'webpack'; import WebpackConfig from '.. /config/Webpack.config'; const buildConfig = new WebpackConfig('production'); webpack(buildConfig).run((err: Error) => { console.log(err); });Copy the code
Add build command to package.json:
"scripts": {
+ "build": "rm -rf ./dist && ts-node ./scripts/build.ts",
"dev": "rm -rf ./dist && ts-node ./scripts/start-dev.ts"
},
Copy the code
Run YARN Build to see dist/server.js. This is the output of our project. Node_modules dependencies are included in node_modules dependencies.
At this point the entire environment setup process is complete.
Full project code MarxJiao/ webpack-Node
conclusion
This project focuses on hot loading and All In Typescript.
1. Why is back-end code hot loaded?
To make it easier to package the front-end code with webPack middleware, you don’t have to recompile the front-end code without restarting the back-end services, which can be time-consuming. In subsequent use, the process would look something like this
Start-dev. ts -> Server -> Server code -> Webpack middleware -> front-end code
This ensures that development starts with only one entry and both ends are hot loaded.
2. Key points of hot loading
- Webpack configuration
mode: 'development'
In order toNamedModulesPlugin
The plug-in - Webpack configuration entry: ‘Webpack /hot/ Signal’
- Pack ‘webpack/hot/signal’ into code: nodeExternals({whitelist: [‘webpack/hot/signal’]})
- use
HotModuleReplacementPlugin
- Start – server – webpack – plugin configuration
signal: true
- Babel configuration
"modules": false
- Tsconfig. Json configuration
"module": "es2015"
- Start the server with a separate file, listen for hot loaded files,
server/server.ts
3. tsconfig
The tsconfig used by TS-Node to run scripts is different from the tsconfig used by TS-Loader to package code.
Ts-node uses config to compile the code directly in TSC and run it in Node. Import is not allowed in earlier versions of Node 8.x, so modules use CommonJS.
Webpack-wrapped code is hot loaded using es Module, in this case using ES2015.
The resources
- Hot reload all the things!
- How to HMR on server side?
- Node.js Web application code hot update alternative ideas
- Don’t use nodemon, there are better ways!
- Webpack does node.js code hot replacement, the first step