配置Webpack Dev Server 实战操作方法步骤
Webpack Dev Server 的实战配置是前端开发者在本地开发中的便捷工具,它能简化繁琐的源码编译和预览流程。本文将详细步骤演示如何配置和使用。源码
首先,源码安装最新版本的源码依赖,确保webpack 5..0、源码安庆wap源码webpack-cli 4.9.2以及webpack-dev-server 4.x。源码在package.json的源码scripts部分,添加启动命令"serve",源码以简化启动服务的源码步骤。
在webpack.config.js文件中,源码新增devServer节点进行配置。源码基础配置如设置服务器监听的源码网页版支付源码地址(如piler?=?webpack(config);?//?这里的server是全局变量?server?=?new?Server(compiler,?options,?log);?if?(options.socket)?{ ?server.listen(options.socket,?options.host,?(err)?=>?{ })?}?else?{ ?server.listen(options.port,?options.host,?(err)?=>?{ })?}?}
深入核心,了解如何通过compiler初始化服务器server对象,源码并且调用listen方法
//?源码webpack-dev-server/lib/Server.js?class?Server?{ ?constructor(compiler,?options?=?{ },?_log)?{ ?//?保存webpack实例?this.compiler?=?compiler;?//?保存用户的配置参数?this.options?=?options;?this.heartbeatInterval?=?;?//?socketServer参数?this.socketServerImplementation?=?getSocketServerImplementation(this.options);?this.sockets?=?[];?//?设置文件监听的目录范围?this.contentBaseWatchers?=?[];?//?开启代码热更新的必备参数?this.hot?=?this.options.hot?||?this.options.hotOnly;?//?文件监听配置?this.watchOptions?=?options.watchOptions?||?{ };?this.setupHooks();?this.setupApp();?this.setupDevMiddleware();?this.createServer();?}?//?使用文件编译结束的钩子?setupHooks()?{ ?const?addHooks?=?(compiler)?=>?{ ?done.tap('webpack-dev-server',?(stats)?=>?{ ?//?服务端编译结束通过websocket告知客户端,以及传递当前的hash值和ok?this._sendStats(this.sockets,?this.getStats(stats));?this._stats?=?stats;?})?}?if?(this.compiler.compilers)?{ ?this.compiler.compilers.forEach(addHooks);?}?else?{ ?addHooks(this.compiler);?}?}?_sendStats(sockets,?stats,?force)?{ ?this.sockWrite(sockets,?'hash',?stats.hash);?this.sockWrite(sockets,?'ok');?}?//?利用express初始化一个服务器,用于静态资源的路由?setupApp()?{ ?this.app?=?new?express();?}?//?配置express搭建后的服务器,确认使用的协议?createServer()?{ ?//?如果使用的协议是piler,?Object.assign({ },?this.options,?{ ?logLevel:?this.log.options.level?})?)?}//?创建websocket服务器,用于下发模块更新的通知到客户端?createSocketServer()?{ ?const?SocketServerImplementation?=?this.socketServerImplementation;?this.socketServer?=?new?SocketServerImplementation(this);?this.socketServer.onConnection((connection,?headers)?=>?{ })?}?//?监听对应的端口开启静态资源路由,同时部署另一个websocket服务器?listen(port,?hostname,?fn)?{ ?return?this.listeningApp.listen(port,?hostname,?(err)?=>?{ ?this.createSocketServer();?}?}?}?//?添加两个打包入口模块,利用webpack将相关代码注入到bundle.js中,用于客户端开启websokct以及处理热模块替换?Server.addDevServerEntrypoints?=?require('./utils/addEntries');?module.exports?=?Server;到这里webpack的HMR在node层做的处理基本完成了,这部分同样是让服务端拥有静态资源路由以及主动下发代码更新通知到客户端的能力,下面看一下如何实现客户端接收websocket通知后主动拉取更新后的服务端代码,并且替换执行新的网页抢单源码模块代码
webpack客户端的代码肯定不会让开发人员自己去实现,不然就会出现千奇百怪的问题。这部分代码处理被黑盒处理,隐藏在了Server.addDevServerEntrypoints方法内,悄悄得在webpack带包过程中添加entry注入这部分代码处理
巧妙地划分客户端能力到两个模块中
//?webpack-dev-server/utils/addEntries.js?function?addEntries(config,?options,?server)?{ ?const?domain?=?createDomain(options,?app);?const?sockHost?=?options.sockHost`&sockHost=${ options.sockHost}`?:?'';?const?sockPath?=?options.sockPath`&sockPath=${ options.sockPath}`?:?'';?const?sockPort?=?options.sockPort`&sockPort=${ options.sockPort}`?:?'';?//?引入搭建websocket客户端代码块module?const?clientEntry?=?`${ require.resolve(?'../../client/'?)}?${ domain}${ sockHost}${ sockPath}${ sockPort}`;?//?处理客户端从服务端获取新模块并且替换执行的代码块module?let?hotEntry;?if?(options.hotOnly)?{ ?hotEntry?=?require.resolve('webpack/hot/only-dev-server');?}?else?if?(options.hot)?{ ?hotEntry?=?require.resolve('webpack/hot/dev-server');?}?}?module.exports?=?addEntries;从这里可以看出来,客户端需要的两个能力被划分到了两个代码模块中,一个是搭建websocket客户端,一个是处理客户端的代码模块更新和替换
搭建websocket客户端
//?webpack-dev-server/client/index.js?var?socket?=?require('./socket');?var?sendMessage?=?require('./utils/sendMessage');?var?createSocketUrl?=?require('./utils/createSocketUrl');?var?reloadApp?=?require('./utils/reloadApp');?var?socketUrl?=?createSocketUrl(__resourceQuery);?var?onSocketMessage?=?{ ?//?接收websocket服务端返回的最新hash值?hash:?function?hash(_hash)?{ ?status.currentHash?=?_hash;?}?ok:?function?ok()?{ ?sendMessage('Ok');?reloadApp(options,?status);?}?}?socket(socketUrl,?onSocketMessage);当客户端收到服务端返回的ok消息推送时,会调用reloadApp,这里看一下具体是怎么处理的
//?webpack-dev-server/client/utils/reloadApp.js?function?reloadApp(_ref,?_ref2)?{ ?if?(hot)?{ ?log.info('[WDS]?App?hot?update...');?var?hotEmitter?=?require('webpack/hot/emitter');?hotEmitter.emit('webpackHotUpdate',?currentHash);?//?如果当前宿主是浏览器环境,则触发webpackHotUpdate消息推送?if?(typeof?self?!==?'undefined'?&&?self.window)?{ ?self.postMessage("webpackHotUpdate".concat(currentHash),?'*');?}?}?}?module.exports?=?reloadApp;所以调用this.postMessage("webpackHotUpdate".concat(currentHash),'*')
有发送就会有接收,找一下对应的回调处理,而处理这部分的抢名额网站源码代码被划分到了hot模块中,根据hash获取新的代码模块并进行替换执行
处理客户端的代码模块更新和替换
//?webpack/hot/dev-server.js?if?(module.hot)?{ ?var?lastHash;?var?check?=?function?check()?{ ?module.hot?.check(true)?.then(function(updatedModules)?{ ?//?容错,如果不存在待更新的模块,直接刷新页面?if?(!updatedModules)?{ ?log("warning",?"[HMR]?Cannot?find?update.?Need?to?do?a?full?reload!");?log(?"warning",?"[HMR]?(Probably?because?of?restarting?the?webpack-dev-server)"?);?window.location.reload();?return;?}?}?.catch(function(err)?{ ?window.location.reload();?}?}?hotEmitter.on("webpackHotUpdate",?function(currentHash)?{ ?lastHash?=?currentHash;?if?(!upToDate()?&&?module.hot.status()?===?"idle")?{ ?log("info",?"[HMR]?Checking?for?updates?on?the?server...");?//?调用check方法拉取更新后的模块代码并进行处理?check();?}?});?}这里的module.hot.check方法,其实是另一位隐藏的大佬进行的方法注入
HotModuleReplacementPlugin
由于涉及到另一个插件的解析,放到后面去扩展。感兴趣的读者可以去webpack/lib/hotModuleReplacement.js阅读源码。
这里重点介绍针对module.hot.check都注入了怎样的代码
//?webpack/lib/web/JsonpMainTemplate.runtime.jsfunction?hotCreateModule(moduleId)?{ ?var?hot?=?{ ?check:?hotCheck?}function?hotCheck(apply)?{ ?hotSetStatus("check");?return?hotDownloadManifest(hotRequestTimeout).then(function(update)?{ ?hotAvailableFilesMap?=?update.c;?hotUpdateNewHash?=?update.h;?hotSetStatus("prepare");})?}?function?hotDownloadManifest(requestTimeout)?{ ?requestTimeout?=?requestTimeout?||?;?return?new?Promise(function(resolve,?reject)?{ ?var?request?=?new?XMLHttpRequest();?var?requestPath?=?__webpack_require__.p?+?""?+?hotCurrentHash?+?".hot-update.json";?request.open("GET",?requestPath,?true);?request.timeout?=?requestTimeout;?request.send(null);?request.onreadystatechange?=?function()?{ ?var?update?=?JSON.parse(request.responseText);?resolve(update);?}?}?}这里之所以使用JSONP的方式获取新的模块代码,是因为JSONP获取的代码可以直接执行,而hash.hot-update.js代码里有个webpackHotUpdate函数调用,最后重点看一下这个函数是如何处理代码模块替换和执行的
//?webpack/lib/HotModuleReplacement.runtime.js?window["webpackHotUpdate"]?=?function?(chunkId,?moreModules)?{ ?hotAddUpdateChunk(chunkId,?moreModules);?};?function?hotAddUpdateChunk(chunkId,?moreModules)?{ ?//?更新的模块moreModules赋值给全局全量hotUpdate?for?(var?moduleId?in?moreModules)?{ ?if?(Object.prototype.hasOwnProperty.call(moreModules,?moduleId))?{ ?hotUpdate[moduleId]?=?moreModules[moduleId];?}?}?//?调webpack3.6.0构建vue项目如何升级vue-devserve?
在老项目中,使用webpack版本3.6.0构建Vue应用时,为解决局域网内共享预览前端项目问题,易语言源码什么需调整webpack-devServer的配置。默认设置host为localhost限制了外部访问,通过设置host为0.0.0.0,使得本机所有ipv4地址用户均可访问。
但自动打开浏览器的默认地址与终端输出运行地址一致,且在Windows环境下无法访问。为解决此问题,需分开设置服务运行地址和服务打开地址。使用命令行指定--host参数为0.0.0.0,优先级最高。
为使浏览器自动打开的地址更加灵活,考虑使用devServer.public配置,但需注意该选项仅适用于webpack v3和v4版本,并且必须设置完整的host:port格式。考虑到实际端口可能被占用,借助portfinder-sync查找可用端口,通过该端口设置devServer.public,确保浏览器可正常访问。
最终解决方案在于直接修改webpack.dev.conf.js文件,利用portfinder设置devWebpackConfig.devServer.public,同时结合address和chalk获取和美化输出本地ipv4地址,实现更灵活的前端服务配置。
对于相关插件和配置优化,建议查阅webpack和webpack-dev-server的官方文档,以获取更多关于配置选项、最佳实践和潜在优化点的信息。
webpack在用dev-server的时候怎么配置多入口文件?
配置 Webpack Dev Server 可以简化本地开发前端应用时的流程,本文将演示配置方法与步骤。 在本地开发前端应用时,手动执行 webpack 命令或 yarn build 后再访问 dist/index.html 非常麻烦。通过配置 Webpack Dev Server 可实现自动启动应用,无需再执行命令。 Webpack Dev Server 的官网地址:webpack.js.org/configur... 安装依赖。确保使用最新版本的 webpack(当前为5..0)、webpack-cli(4.9.2)和 webpack-dev-server(4.9.3)。 在 package.json 文件的 scripts 节点添加启动 webpack dev server 的命令: "serve": "webpack serve"。 修改 webpack 配置文件(webpack.config.js),在 entry、plugins、mode 同级新增 devServer 配置: 配置示例: devServer: { host: 'localhost', port: , hot: true, allowedHosts: 'all' } 启动服务。执行 "yarn serve" 命令,启动 webpack dev server。访问 http://localhost: 即可访问应用。高效开发的配置
devtool 配置。默认情况下,打印的日志和报错显示打包后的代码位置。将 devtool 配置为 source-map,以实现源码映射,便于快速定位问题。 HMR(Hot Module Replacement)配置。在运行中修改代码时,自动替换、添加或删除相关模块,无需重新打包所有模块。通过在 devServer 配置中开启 hot: true 实现。HMR 实际应用
HMR 支持在程序运行中修改代码并实时生效,但 JS 效果可能不会立即显现。对于现代化开发环境(如 Vue),通过实现组件级别的 HMR,仅替换修改的部分组件,大大提升了开发效率。2024-12-23 06:30
2024-12-23 05:52
2024-12-23 05:44
2024-12-23 05:21
2024-12-23 05:17