2023年7月7日发(作者:)
使⽤webpack搭建基于TypeScript的node开发环境正在学习,这⾥介绍使⽤webpack来搭建基于TypeScript的node开发环境。整个环境的必备功能⼀套好的开发环境能让开发者专注于代码,⽽不必关系其它事情。这⾥先列出⼀些必要的条件。1. ⼀个命令就能启动项⽬。2. ⼀个命令能打包项⽬。3. 开发时代码改动能够⾃动更新,最好是热更新,⽽不是重启服务,这⾥为后⾯和前端代码⼀起调试做准备。4. 开发中能使⽤编辑器或者chrome调试,我本⼈习惯使⽤vscode。基本搭建思路全局使⽤ts,包括脚本,webpack配置⽂件。使⽤npm调⽤ts脚本,脚本使⽤ts-node执⾏,使⽤ts脚本调⽤webpack的api来打包编译⽂件。npm scipts -> -> webpack(webpackConfig)这⾥解释下为什么使⽤ts脚本来调⽤webpack⽽不是直接将webpack命令写在npm scripts⾥。我的想法是All In Typescrpt,尽量做到能⽤ts的就不⽤js,使⽤webpack的node api能轻松实现⽤ts写webpack配置。这样把做还有⼀个好处就是可以把webpack的配置写成动态的,根据传⼊参数来⽣成需要的配置。选型到这⾥项⽬的选型已经很明了了。TypeScript 项⽬使⽤的主语⾔,为前端开发添加强类型⽀持,能在编码过程中避免很多问题。Koa 应⽤⽐较⼴泛。没有附加多余的功能,中间件即插即⽤。Webpack 打包⼯具,开发中热加载。ts-node ⽤来直接执⾏ts脚本。start-server-webpack-plugin 很关键的webpack插件,能够在编译后直接启动服务,并且⽀持signal模式的热加载,配合webpack/hot/signal很好⽤。环境搭建我们先⽤Koa写⼀个简单的web server,之后针对这个server来搭建环境。项⽬代码新建server/,这个⽂件主要⽤来创建⼀个koa app。import * as Koa from 'koa';const app = new Koa();(ctx => { = 'Hello World';});export default app;我们需要另⼀个⽂件来启动server,并且监听server/的改变,来热加载项⽬。新建server/rt * as http from 'http';import app from './app';// ck() 会返回⼀个能够通过Server创建server的函数,类似express和connect。let currentApp = ck();// 创建serverconst server = Server(currentApp);(3000);// 热加载if () { // 监听./ ('./', () => { // 如果有改动,就使⽤新的app来处理请求 Listener('request', currentApp); currentApp = ck(); ('request', currentApp); });}编译配置在写webpack配置之前,我们先写下ts配置和babel配置。TypeScrript配置ipt配置这⾥写的是webpack编译代码⽤的配置,后⾯还会介绍ts-node跑脚本时使⽤的配置。我们新建config/:{ "compilerOptions": { // module配置很重要,千万不能配置成commonjs,热加载会失效 "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", "**/*." ]}babel配置.babelrc,"modules": false很重要,tree shaking、HMR都靠它。{ "presets": [["env", {"modules": false}]]}webpack配置⼀般情况下需要准备2套webpack配置,⼀套⽤来开发,⼀套⽤来发布。前⾯已经说过了使⽤webpack的api来打包为动态创建webpack配置提供了可能。所以这⾥我们写⼀个WebpackConfig类,创建实例时根据参数,⽣成不同环境的配置。开发环境和发布环境的区别⾸先两个环境的mode是是不同的,开发环境是development,发布环境是production。关于mode的更多信息可查看webpack⽂档。开发环境需要热加载和启动服务,entry⾥需要配置'webpack/hot/signal',使⽤webpack-node-externals将'webpack/hot/signal'打包到代码⾥,添加HotModuleReplacementPlugin,使⽤start-server-webpack-plugin启动服务和开启热加载。webpack配置内容现在我们来写下webpack配置。重点写在注释中了。新建⽂件config/。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环境 target: Configuration['target'] = "node"; // 默认为发布环境 mode: Configuration['mode'] = 'production'; // ⼊⼝⽂件 entry = [e(__dirname, '../server/')]; output = { output = { path: e(__dirname, '../dist'), filename: "" }; // 这⾥为开发环境留空 externals: ExternalsElement[] = []; // loader们 module = { rules: [ { test: /.tsx?$/, use: [ // tsc编译后,再⽤babel处理 {loader: 'babel-loader',}, { loader: 'ts-loader', options: { // 加快编译速度 transpileOnly: true, // 指定特定的ts编译配置,为了区分脚本的ts配置 configFile: e(__dirname, './') } } ], exclude: /node_modules/ }, { test: /.jsx?$/, use: 'babel-loader', exclude: /node_modules/ } ] }; resolve = { extensions: [".ts", ".js", ".json"], }; // 开发环境也使⽤NoEmitOnErrorsPlugin plugins = [new OnErrorsPlugin()]; constructor(mode: Configuration['mode']) { // 配置mode,production情况下⽤上边的默认配置就ok了。 = mode; if (mode === 'development') { // 添加webpack/hot/signal,⽤来热更新 ('webpack/hot/signal'); ( // 添加webpack/hot/signal,⽤来热更新 nodeExternals({ whitelist: ['webpack/hot/signal'] }) ); const devPlugins = [ // ⽤来热更新 new uleReplacementPlugin(), // 启动服务 new StartServerPlugin({ // 启动的⽂件 name: '', // 开启signal模式的热加载 signal: true, // 为调试留接⼝ nodeArgs: ['--inspect'] }), ] (...devPlugins); } }}export default WebpackConfig;编译脚本使⽤ts-node来启动脚本时需要使⽤新,这个编译⽬标是在node中运⾏。在项⽬根⽬录新建:{ "compilerOptions": { // 为了node环境能直接运⾏ "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", "**/*." ]}开发脚本启动开发脚本,scripts/:import * as webpack from 'webpack';import WebpackConfig from '../config/';// 创建编译时配置const devConfig = new WebpackConfig('development');// 通过watch来实时编译webpack(devConfig).watch({ aggregateTimeout: 300}, (err: Error) => { (err);});在中添加"scripts": { "dev": "rm -rf ./dist && ts-node ./scripts/"},执⾏yarn dev,我们能看到项⽬启动了:命令⾏输出:命令⾏输出浏览器展⽰:浏览器展⽰修改server/rt * as Koa from 'koa';const app = new Koa();(ctx => {- = 'Hello World';+ = 'Hello Marx';});export default app;能看到命令⾏输出:更新代码后命令⾏输出刷新浏览器:浏览器展⽰可以看到热更新已经⽣效了。发布打包脚本新建打包脚本scripts/:import * as webpack from 'webpack';import WebpackConfig from '../config/';const buildConfig = new WebpackConfig('production');webpack(buildConfig).run((err: Error) => { (err);});在添加build命令:"scripts": {+ "build": "rm -rf ./dist && ts-node ./scripts/", "dev": "rm -rf ./dist && ts-node ./scripts/"},执⾏yarn build就能看到dist/。这个就是我们项⽬的产出。其中包含了node_modules中的依赖,这样做是否合理,还在探索中,欢迎讨论。到此整个环境搭建过程就完成了。完整项⽬代码MarxJiao/webpack-node总结这个项⽬重点在于热加载和All In TypeScript。1. 为什么后端代码要热加载?为了⽅便使⽤webpack中间件打包前端代码,这样不⽤重启后端服务就不⽤重新编译前端代码,重新编译是很耗时的。后续使⽤时,流程⼤概是这样的 -> server端的webpack -> server代码 -> webpack中间件 -> 前端代码这样能保证开发时只需要⼀个⼊⼝来启动,前后端都能热加载。2. 实现热加载的关键点webpack配置mode: 'development',为了NamedModulesPlugin插件webpack配置entry: 'webpack/hot/signal'将'webpack/hot/signal'打包进代码:nodeExternals({whitelist: ['webpack/hot/signal']})使⽤HotModuleReplacementPluginstart-server-webpack-plugin配置signal: truebabel配置"modules": 配置"module": "es2015"使⽤单独的⽂件来启动server,监听热加载的⽂件,server/3. tsconfigts-node运⾏脚本的tsconfig和ts-loader打包代码时的tsconfig不同。ts-node⽤的config直接将代码⽤tsc编译后在node运⾏,在node 8.x以下的版本中不能使⽤import,所以module要⽤commonjs。webpack打包的代码要热加载,需要⽤es module,这⾥我们使⽤es2015。参考资料Hot reload all the things!How to HMR on server side? Web应⽤代码热更新的另类思路Don’t use nodemon, there are better ways!Webpack 做 代码热替换, 第⼀步
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1688683885a162294.html
评论列表(0条)