久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

我們?nèi)绾问褂?Webpack 將啟動時間減少 80%

 黃爸爸好 2022-05-07 發(fā)布于上海

圖片

我們在 RudderStack 使用的開發(fā)方式之一是安全快速地構(gòu)建,然后根據(jù)需要進行優(yōu)化,,這種模式使我們能夠優(yōu)先考慮客戶問題,,跟上 RudderStack 的快速增長的腳步。

但在某些情況下,,這種方式會導(dǎo)致開發(fā)體驗的流失,。發(fā)生這種情況時,我們使用帕累托原則重新集中精力,,力求在消除技術(shù)債務(wù)中投入的時間能得到最大的回報,。

這種不太好的開發(fā)體驗的一個例子是 Control Plane 的主后端服務(wù)的部署時間過長。過去在生產(chǎn)環(huán)境中部署需要 5 分鐘,,更甚的是,,在開發(fā)過程中,根據(jù)硬件的不同,,重啟需要 40-90 秒,,這成了一個主要的痛點,拖慢了我們團隊的進度,,我們知道,,是時候重新關(guān)注和解決它了,我們是這樣做的,。

Control Plane 是什么,?

首先,我解釋一下我所說的“Control Plane(控制臺)”,,Rudderstack 的架構(gòu)分為兩部分:數(shù)據(jù)臺和控制臺,。控制臺是 Rudderstack 平臺的大腦,,它是存儲資源和配置的地方,,你的組織、工作區(qū),、基礎(chǔ)設(shè)施和賬單中的用戶管理和協(xié)作都在控制臺中進行,。

圖片

從架構(gòu)的角度來看,控制臺由一個以集群模式運行的后端應(yīng)用,、幾個附屬微服務(wù)和一個前端應(yīng)用組成,。對于我們的后端服務(wù),我們使用 Node.js 和 Typescript,,用 ts-node 來啟動和運行應(yīng)用程序,。但是如上所述,,這是有代價的,讓我們深入了解里面發(fā)生了什么,。

解決我們啟動時間的問題

我們知道 Node.js 不是問題的原因,,原生的 HTTP 服務(wù)器幾乎是立即重啟,我們使用的 koa web 框架精簡且輕量級,。所以,,我們需要做一些分析來查明原因,使用 clinic.js 來幫助分析,,它簡單而易用,。

果然,在設(shè)置好 clinic 并進行了幾次測試運行之后,,我們生成了一些火焰圖(火焰圖是一種顯示每個方法和依賴項需要多少執(zhí)行(CPU)時間的方式),,它們揭示了問題。

帶有源代碼和過程的火焰圖:

圖片

沒有源代碼的過程火焰圖:

圖片

不管是否包含 rudder-config-backend 源代碼,,圖表都是一樣的,,所以我們知道源代碼不是問題,并且可以確定開銷來自 Typescript,,尤其是 ts-node,。

這是有道理的,因為每當(dāng)進程重新啟動時,,整個源代碼都必須從零開始轉(zhuǎn)換為 Javascript,,而且沒有任何緩存;這與我們在集群模式下部署服務(wù)器時遇到的較大延遲一致,。每個工作進程都必須獨立編譯 Typescript 文件,,因此重新啟動需要很多時間,有時還會導(dǎo)致資源匱乏,。具體來說,,我們在服務(wù)器啟動期間,可以看到內(nèi)存不足錯誤和 CPU 利用率在增加,。

雖然在生產(chǎn)中使用 ts-node 并不是一種壞的做法 (如果設(shè)置得當(dāng)),,但在我們的案例中,我們意識到它會產(chǎn)生大量的開銷,,然而我們嚴重依賴 TypeORM 和 reflect-metadata,,這使得 ts-node 很有吸引力。消除這種依賴需要大量的工作,,并可能通過限制我們的工具集而導(dǎo)致 DX 的進一步退化,。所以,我們只有一個選擇:刪除 Typescript,。

當(dāng)然,,不是完全刪除 Typescript,,只是在生產(chǎn)環(huán)境。至少在理論上,,讓一個 node 進程加載.js 文件,而不是用 ts-node 包裝器,,這將大大減少啟動時間,,正如我們在第二個火焰圖中觀察到的那樣。當(dāng)然,,我們可以采取不同的方法來實現(xiàn)這一點,,但每一種方法都有利弊。

方法一:使用 tsc

我們最初的方法是使用 tsc 二進制文件,,和安裝的 Typescript 版本一起打包,,并增加一個編譯步驟。事實證明,,這比想象的更棘手,,因為幾位工程師在 2 年多的時間里用不同的方法開發(fā)了配置的后端。因此,,我們遇到了一些問題:

  • 多個依賴項用了不同的模塊,,tsc 一次只能處理一種方式。

  • Typescript 輸出一個真實的,、一對一的源到分發(fā)目錄,、使用了不同格式的 imports —— 有些是相對于 package.json,有些是別名,。

  • Typescript 在設(shè)計上不會修改依賴項的導(dǎo)入路徑,,帶有模塊的 Node.js 對文件名應(yīng)該如何表示有嚴格的要求。

方法二:用 ttypescript 和 ttsc 擴展 Typescript

可以使用幾個補丁來修改 tsc 的行為,,繞過 Typescript 的轉(zhuǎn)譯限制,。不幸的是,這些解決方案雖然不是很復(fù)雜,,但需要需要大量的混合和匹配來覆蓋所有用例,,并且對項目添加了額外的依賴項,例如 typescript-transformer-append-js-extension,。

退一步說,,我們意識到將不得不犧牲 Typescript 模塊提供的一些便利,并重寫應(yīng)用程序的某些部分,,尤其是在導(dǎo)入模塊方面,。

但是,如果有一個解決方案可以找出依賴關(guān)系,,以及如何以聲明的方式導(dǎo)入它們呢?

進入 webpack

webpack 是一個傳統(tǒng)的 JavaScript 模塊打包器,,創(chuàng)建的目的是通過有效地將前端應(yīng)用分割成塊,,快速地將其傳送到用戶的瀏覽器。作為最古老,、最成熟的打包工具之一,,至今仍在積極地維護中,webpack 擁有一個龐大的插件生態(tài)系統(tǒng),,適應(yīng)任何類型的復(fù)雜應(yīng)用,,并且它對 Node.js 提供了一流的支持。

由于 webpack 就是為此目的而構(gòu)建的,,讓它來處理模塊解析和轉(zhuǎn)換.ts 文件,,相比其它類 hack 和猴子補丁方法,感覺更自然,。我們努力了幾次讓 webpack 與 TypeORM 一起工作,,主要是因為 TypeORM 頑固的設(shè)定。例如,,數(shù)據(jù)庫遷移文件必須在類名末尾包含時間戳,,這意味著源文件不能縮小,導(dǎo)入 / 導(dǎo)出名稱不能被篡改,。但經(jīng)過幾次嘗試,,我們成功了。果然,,通過 webpack 及其插件處理,,每個文件都簡化了構(gòu)建過程。通過高效緩存,,后續(xù)構(gòu)建的速度會更快,,從而獲得更好的 DX 和更短的部署窗口。集群模式的部署現(xiàn)在大約需要 12 秒,,縮短了近 5 分鐘,!——從服務(wù)請求開始。請記住,,這是 8 個節(jié)點進程共享的資源,,每個節(jié)點進程啟動一個 koa 的 web 服務(wù)器和通過 TypeORM 連接到數(shù)據(jù)庫。

在開發(fā)過程中,,結(jié)果更加突出:


之前(秒

之后(秒

改進 (%

冷啟動構(gòu)建時間

40 ~ 90

9  ~ 13

77 ~ 85

熱重啟時間


0.5 ~ 0.9

服務(wù)器就緒

與冷啟動相同

1

97 ~ 98

以下是我們用來大幅減少啟動時間的 webpack 配置:

  1. 安裝需要的依賴:

npm install --save-dev webpack webpack-cli @types/webpack-env

webpack 和 webpack-cli 不言自明,,第三個包 @types/webpack-env,會啟用 webpack 的 require.Context 的自動完成功能,,這需要手動指導(dǎo) webpack 如何以元編程的方式處理符號,,例如,在源代碼目錄中找到你的 ORM 實體并自動聲明它們,,而不是專門地一個個導(dǎo)入——我們有大量這樣的實體,!

注意:所有這些依賴項只能在開發(fā)和構(gòu)建期間使用,,不需要在生產(chǎn)構(gòu)建中加載它們!

  1. 創(chuàng)建和導(dǎo)出配置文件

webpack 的配置非常簡單,,只需在你的項目根目錄(通常是 package.json 所在的文件夾)中創(chuàng)建一個 webpack.config.js 文件,,然后導(dǎo)出 webpack 配置,。它看起來可能像這樣:

module.exports = {// webpack config}
  1. 添加構(gòu)建入口和路徑

module.exports = { entry: './src/index.ts', // the file you would provide to ts-node or node binaries for execution mode: NODE_ENV, // development or production target: 'node', // webpack works differently based on target, here we use node.js output: { // directions for the built files directory path: path.resolve(__dirname, 'dist'), filename: 'index.js', },}
  1. 配置如何查找源代碼文件

module.exports = {  // ...  resolve: {  // Bundle only typescript files  extensions: ['.ts'],  alias: {    // provide any import aliases you may use in your project    src: path.resolve(__dirname, 'src/'),    '@controller': path.resolve(__dirname, 'src/controllers/'),    '@service': path.resolve(__dirname, 'src/services/'),  },  },}
  1. 配置讀取 ts 文件

對于這一步,,你可以安裝任何你喜歡的 webpack 的 typescript 加載器。我們使用 ts-loader:

npm install --save-dev ts-loader
module.exports = {  // ...  module: {  rules: [    {      test: /\.ts$/,   // this rule will only activate for files ending in .ts      use: [{ loader: 'ts-loader' }],        exclude: [  // exclude any files you don't want to include        /__tests__/,      ],    },  ],  },}
  1. 添加外部擴展,,這樣 webpack 就不會打包外部依賴(node 模塊)

npm install --save-dev webpack-node-externals
module.exports = {  // ...  externals: [nodeExternals()],}
  1. 別忘了你的插件——webpack 一切與插件相關(guān),!

module.exports = { // ... plugins: [ ...plugins, ],}

下面是我們使用的一些插件的列表,,向出色的貢獻者和維護者致敬,!

  • nodemon-webpack-plugin:nodemon 的標(biāo)準(zhǔn)包裝器,,使開發(fā)速度更快。

  • webpack-shell-plugin-next:添加構(gòu)建生命周期鉤子來運行 cli 命令,,例如,,在構(gòu)建源文件之前構(gòu)建 swagger 文件。

  • fork-TS-checker-webpack-plugin:在一個獨立進程上運行 TS 類型檢查器,,以提高構(gòu)建期間的性能,。注意:如果你使用這個,請確保更新步驟 5 中的 module.rules.use 為:{loader: 'ts-loader',, options: {transpileOnly: true}},,這樣 ts-loader 就不會運行類型檢查。

最終的 webpack 配置

你最終的 webpack 配置應(yīng)該是這樣的:

const path = require('path');const nodeExternals = require('webpack-node-externals');
const { NODE_ENV = 'production',} = process.env;
module.exports = { entry: './src/index.ts', // the file you would provide to ts-node or node binaries for execution mode: NODE_ENV, // development or production target: 'node', // webpack works differently based on target, here we use node.js output: { // directions for the built files directory path: path.resolve(__dirname, 'dist'), filename: 'index.js', }, resolve: { // Bundle only typescript files extensions: ['.ts'], alias: { // provider any import aliases you may use in your project src: path.resolve(__dirname, 'src/'), '@controller': path.resolve(__dirname, 'src/controllers/'), '@service': path.resolve(__dirname, 'src/services/'), }, }, module: { rules: [ { test: /\.ts$/, // this rule will only activate for files ending in .ts use: [{ loader: 'ts-loader' }], exclude: [ // exclude any files you don't want to include, eg test files /__tests__/, ], }, ], }, externals: [nodeExternals()], plugins: [ // any plugins you may find useful ],}
優(yōu)化為更多的優(yōu)化鋪平道路

我們從運行時的依賴項中刪除了 Typescript,,所以我們在最終的生產(chǎn)制品中不再需要它,,這樣我們完全擺脫了這些依賴!

它也啟發(fā)我們優(yōu)化了構(gòu)建流水線,,通過引入帶緩存層,、和為開發(fā)和生產(chǎn)不同目標(biāo)的多階段 docker 構(gòu)建,使其更為高效,。

更少的依賴意味著:

  • 更小的圖像尺寸,。

  • 減少第三方代碼造成的內(nèi)存泄漏的機會。

  • 更少的帶寬使用,。

  • 更快的傳輸時間,。

最重要的是,它意味著面臨更少的攻擊,,由于依賴更少,、審計和解決漏洞的時間更少,讓 RudderStack 對我們的客戶來說更加安全,。

原文鏈接:

https://www./blog/how-we-reduced-startup-time-by-80-with-webpack/

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多