🔍 搜尋結果:javascript

🔍 搜尋結果:javascript

Javascript 中的高階函數

## 介紹 在 Javascript 中,函數就是值(一等公民)。這意味著它們可以分配給變數和/或作為值傳遞。 ``` let random = function(){ return Math.random() } let giveMeRandom = random // assigning random to a variable ``` 這項知識使我們能夠用這種語言編寫函數式程式設計。在函數式程式設計中,我們大量使用高階函數。 ## 高階函數? 高階函數是將其他函數作為參數*或*返回函數作為結果的函數。 以其他函數作為參數通常稱為“回調函數”,因為它是由高階函數回調的。這是 Javascript 常用的概念。 例如,陣列上的 *map* 函數是一個高階函數。 *map* 函數接受一個函數作為參數。 ``` const double = n => n * 2 [1, 2, 3, 4].map(double) // [ 2, 4, 6, 8 ] ``` 或者,使用匿名函數: ``` [1, 2, 3, 4].map(function(n){ return n * 2 }) // [ 2, 4, 6, 8 ] ``` *map* 函數是該語言內建的眾多高階函數之一。 *sort*、*reduce*、*filter*、*forEach* 是該語言內建的高階函數的其他範例。 高階函數可讓您編寫更簡單、更優雅的程式碼。讓我們看看如果沒有這樣的抽象,上面的程式碼會是什麼樣子。讓我們用循環取代 *map* 函數: ``` let array = [1, 2, 3, 4] let newArray = [] for(let i = 0; n < array.length; i++) { newArray[i] = array[i] * 2 } newArray // [ 2, 4, 6, 8 ] ``` ## 組合的力量 盡可能使用高階函數的一大優點是組合。 我們可以建立更小的函數,只處理一個邏輯。然後,我們透過使用不同的較小函數來組合更複雜的函數。 這種技術減少了錯誤並使我們的程式碼更易於閱讀和理解。 透過學習使用高階函數,您可以開始編寫更好的程式碼。 ## 例子 讓我們試著舉個例子。假設我們有一個教室的成績清單。我們的教室有 5 個女孩,5 個男孩,每個人的成績都在 0 到 20 之間。 ``` var grades = [ {name: 'John', grade: 8, sex: 'M'}, {name: 'Sarah', grade: 12, sex: 'F'}, {name: 'Bob', grade: 16, sex: 'M'}, {name: 'Johnny', grade: 2, sex: 'M'}, {name: 'Ethan', grade: 4, sex: 'M'}, {name: 'Paula', grade: 18, sex: 'F'}, {name: 'Donald', grade: 5, sex: 'M'}, {name: 'Jennifer', grade: 13, sex: 'F'}, {name: 'Courtney', grade: 15, sex: 'F'}, {name: 'Jane', grade: 9, sex: 'F'} ] ``` 我想了解一些關於此事的事情: - 該班的平均成績 - 男生的平均成績 - 女孩的平均成績 - 男孩中音調較高的 - 女孩中的最高調 我們將嘗試使用高階函數來獲得簡單易讀的程式。讓我們從編寫可以協同工作的簡單函數開始: ``` let isBoy = student => student.sex === 'M' let isGirl = student => student.sex === 'F' let getBoys = grades => ( grades.filter(isBoy) ) let getGirls = grades => ( grades.filter(isGirl) ) let average = grades => ( grades.reduce((acc, curr) => ( acc + curr.grade ), 0) / grades.length ) let maxGrade = grades => ( Math.max(...grades.map(student => student.grade)) ) let minGrade = grades => ( Math.min(...grades.map(student => student.grade)) ) ``` 我寫了7個函數,每個函數都有一份工作,而且只有一份工作。 *isBoy* 和 *isGirl* 負責檢查一名學生是男孩還是女孩。 *getBoys* 和 *getGirls* 負責將所有男孩或女孩帶出教室。 *maxGrade* 和 *minGrade* 負責取得某些資料中的最高和最低等級。 最後,*average*負責計算一些資料的平均等級。 請注意,*average* 函數還不知道它要處理的資料類型。這就是構圖之美。我們可以在不同的地方重複使用我們的程式碼。我可以將此功能與其他功能一起使用。 現在,我們已經有了編寫高階函數所需的東西: ``` let classroomAverage = average(grades) // 10.2 let boysAverage = average(getBoys(grades)) // 7 let girlsAverage = average(getGirls(grades)) // 13.4 let highestGrade = maxGrade(grades) // 18 let lowestGrade = minGrade(grades) // 2 let highestBoysGrade = maxGrade(getBoys(grades)) // 16 let lowestBoysGrade = minGrade(getBoys(grades)) // 2 let highestGirlsGrade = maxGrade(getGirls(grades)) // 18 let lowestGirlsGrade = minGrade(getGirls(grades)) // 9 ``` 請注意,外部函數(例如*average*)始終將內部函數的輸出作為輸入。因此,組合的唯一條件是確保輸出和輸入匹配。 而且因為每個函數只負責一件事,所以它使我們的程式碼更容易除錯和測試。 --- 原文出處:https://dev.to/damcosset/higher-order-functions-in-javascript-4j8b

JS 設計模式:綜合指南

![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vukjahraekzzsj9e6h3x.png) JavaScript 以其廣泛的採用和多功能性,已成為現代 Web 開發的基石。隨著您深入研究 JavaScript 開發,理解和利用模式變得至關重要。在本文中,我們將踏上揭開 JavaScript 模式神秘面紗的旅程,並探索它們如何增強您的程式設計實踐。 ## 先決條件 要理解本文中討論的概念和技術,您需要了解 JavaScript 的基礎知識。熟悉變數、函數、資料類型、物件導向程式設計等概念至關重要。 在繼續之前,讓我們花點時間了解 JavaScript 作為程式語言的重要性。 ### JavaScript 作為程式語言 JavaScript 通常被稱為“網路語言”,是一種動態的高階程式語言。它主要用於 Web 瀏覽器中的客戶端腳本編寫,但隨著 Node.js 的出現,它也在伺服器端獲得了關注。 JavaScript 的主要功能包括操作 DOM、處理事件、為網頁提供互動性等的能力。 話雖這麼說,讓我們簡單討論一下 JavaScript 中模式的重要性和用途。 ### JavaScript 開發中模式的重要性 JavaScript 中的模式可以作為軟體開發過程中遇到的重複問題的經過驗證的解決方案。它們提供結構、改進程式碼組織、增強可維護性並促進可重複使用性。透過理解和應用模式,開發人員可以編寫更清晰、更有效率的程式碼並有效應對複雜的挑戰。 ### 理解 JavaScript 模式的目的 理解 JavaScript 模式不僅僅是記住文法或遵循最佳實踐。它使開發人員能夠批判性地思考軟體設計、選擇適當的解決方案並建立可擴展的應用程式。透過掌握 JavaScript 模式,您可以深入了解該語言及其生態系統,從而能夠編寫健全且可維護的程式碼。 現在我們知道了 JavaScript 模式的重要性和用途,讓我們深入研究 JS 設計模式的基礎知識。 ## 設計模式的基礎知識 在本節中,我們為理解 JavaScript 開發背景下的設計模式奠定了基礎。 ###設計模式的定義與特點 設計模式是可重複使用的模板,封裝了解決重複出現的軟體設計問題的最佳實踐。它們提供了一種結構化的方法來設計軟體系統,並促進模組化、靈活和可維護的程式碼。設計模式的共同特徵包括其目的、結構、參與者和協作。 ###設計模式的類型 設計模式可分為三種主要類型: - 創意 - 結構性 - 行為的 了解這些類別有助於確定給定問題的適當模式。 - **創作模式** 建立模式專注於物件建立機制,提供以靈活且受控的方式實例化物件的方法。 JavaScript 中一些常用的建立模式包括: - 辛格頓 - 工廠 - 建構函數 - 原型 - 建造者 - 模組 **單例模式** 單例模式確保一個類別只有一個實例,並提供對其的全域存取點。當您想要限制類別的實例數量並確保在整個應用程式中可以存取單一共用實例時,此模式非常有用。 ``` // Implementation example of the Singleton Pattern class Singleton { constructor() { if (!Singleton.instance) { // Initialize the instance Singleton.instance = this; } return Singleton.instance; } } const instance1 = new Singleton(); const instance2 = new Singleton(); console.log(instance1 === instance2); // Output: true ``` 在此範例中,Singleton 類別有一個建構函數,用於檢查該類別的實例是否已存在。如果實例不存在(“!Singleton.instance”條件),它將透過將其指派給「Singleton.instance」來初始化該實例。這確保了對建構函數的後續呼叫將傳回相同的實例。 當使用新的 Singleton() 語法建立實例 1 和實例 2 時,這兩個變數都會引用 Singleton 類別的同一個實例。因此,當使用嚴格相等運算子比較實例 1 === 實例 2 時,其計算結果為 true。 **工廠模式** 工廠模式提供了一種建立物件而無需指定其特定類別的方法。它將物件建立邏輯封裝在一個單獨的工廠方法中,允許建立者和建立的物件之間的靈活性和解耦。 ``` // Implementation example of the Factory Pattern class Car { constructor(make, model) { this.make = make; this.model = model; } } class CarFactory { createCar(make, model) { return new Car(make, model); } } const factory = new CarFactory(); const myCar = factory.createCar("Tope", "Model 1"); ``` 在此範例中,使用 new CarFactory() 建立了一個 CarFactory 實例,然後使用參數「Tope」和「Model 1」在工廠上呼叫「createCar」方法。這將建立一個新的 Car 物件,其品牌為“Tope”,型號為“Model 1”,並分配給 `myCar` 變數。 **建構函式模式** 建構函式模式使用“new”關鍵字從建構函式建立物件。它允許您在建構函數中定義和初始化物件屬性。 ``` // Implementation example of the Constructor Pattern function Person(name, age) { this.name = name; this.age = age; } const tope = new Person("Tope", 24); ``` 上面的程式碼定義了一個名為 Person 的建構函數,它帶有兩個參數:姓名和年齡。在函數內部,使用 this 關鍵字將名稱和年齡值指派給新建立的物件的對應屬性。 稍後,透過使用參數“Tope”和 24 呼叫 Person 函數來建立 Person 物件的新實例。這將建立一個新物件,其 name 屬性設為“Tope”,age 屬性設為 24,然後指派給變數top。這段程式碼的輸出是 Tope 持有一個物件,代表一個名為「Tope」、年齡為 24 歲的人。 **原型模式** JavaScript 中的原型模式專注於透過複製或擴展現有物件作為原型來建立物件。它允許我們建立新實例而無需明確定義它們的類別。在此模式中,物件充當建立新物件的原型,從而實現繼承以及在多個物件之間共享屬性和方法。 ``` // Prototype object const carPrototype = { wheels: 4, startEngine() { console.log("Engine started."); }, stopEngine() { console.log("Engine stopped."); } }; // Create new car instance using the prototype const car1 = Object.create(carPrototype); car1.make = "Toyota"; car1.model = "Camry"; // Create another car instance using the same prototype const car2 = Object.create(carPrototype); car2.make = "Honda"; car2.model = "Accord"; car1.startEngine(); // Output: "Engine started." car2.stopEngine(); // Output: "Engine stopped." ``` 在此範例中,汽車實例 car1 和 car2 是使用原型物件 carPrototype 建立的。 car1 的品牌為“Toyota”,型號為“Camry”,而 car2 的品牌為“Honda”,型號為“Accord”。當呼叫 `car1.startEngine()` 時,輸出“Engine started.”,當呼叫 `car2.stopEngine()` 時,輸出“Engine waiting.”。這示範如何利用原型物件在多個實例之間共用屬性和方法。 **建造者模式** 在建構器模式中,建構器類別或物件負責建構最終物件。它提供了一組方法來配置和設定正在建置的物件的屬性。建置過程通常涉及按特定順序呼叫這些方法來逐步建立物件。 ``` class CarBuilder { constructor() { this.car = new Car(); } setMake(make) { this.car.make = make; return this; } setModel(model) { this.car.model = model; return this; } setEngine(engine) { this.car.engine = engine; return this; } setWheels(wheels) { this.car.wheels = wheels; return this; } build() { return this.car; } } class Car { constructor() { this.make = ""; this.model = ""; this.engine = ""; this.wheels = 0; } displayInfo() { console.log(`Make: ${this.make}, Model: ${this.model}, Engine: ${this.engine}, Wheels: ${this.wheels}`); } } // Usage const carBuilder = new CarBuilder(); const car = carBuilder.setMake("Toyota").setModel("Camry").setEngine("V6").setWheels(4).build(); car.displayInfo(); // Output: Make: Toyota, Model: Camry, Engine: V6, Wheels: 4 ``` 在此範例中,「CarBuilder」類別允許建構具有不同屬性的 Car 物件。透過呼叫`setMake`、`setModel`、`setEngine`、`setWheels`方法,設定Car物件的屬性。 build 方法完成建置並傳回完全建置的 Car 物件。 Car 類別代表一輛汽車,並包含一個「displayInfo」方法來記錄其詳細資訊。透過建立「carBuilder」實例並連結屬性設定方法,可以使用特定的品牌、型號、引擎和車輪值來建構汽車物件。呼叫“car.displayInfo()”顯示汽車的資訊。 **模組模式** 模組模式將相關的方法和屬性封裝到單一模組中,提供了一種乾淨的方式來組織和保護程式碼。它允許私有和公共成員,從而實現資訊隱藏並防止全域名稱空間污染。 ``` const MyModule = (function() { // Private members let privateVariable = "I am private"; function privateMethod() { console.log("This is a private method"); } // Public members return { publicVariable: "I am public", publicMethod() { console.log("This is a public method"); // Accessing private members within the module console.log(privateVariable); privateMethod(); } }; })(); // Usage console.log(MyModule.publicVariable); // Output: "I am public" MyModule.publicMethod(); // Output: "This is a public method" "I am private" "This is a private method" ``` 在此範例中,程式碼使用立即呼叫的函數表達式來封裝私人和公共成員。該模組具有私有變數和方法,以及公共變數和方法。存取時,公共成員提供預期的輸出。此模式允許對封裝的私有成員進行受控存取,同時公開選定的公共成員。 - **結構模式** 結構模式著重於組織和組合物件以形成更大的結構。它們促進物件的組合,定義物件之間的關係並提供靈活的方法來操縱其結構。 JavaScript 中一些常用的結構模式包括: - 裝飾模式 - 立面圖案 - 適配器 - 橋 - 合成的 **裝飾器模式** 裝飾器模式可讓您動態新增行為或修改物件的現有行為。它透過用一個或多個裝飾器包裝物件來增強物件的功能,而無需修改其結構。 ``` // Implementation example of the Decorator Pattern class Coffee { getCost() { return 1; } } class CoffeeDecorator { constructor(coffee) { this.coffee = coffee; } getCost() { return this.coffee.getCost() + 0.5; } } const myCoffee = new Coffee(); const coffeeWithMilk = new CoffeeDecorator(myCoffee); console.log(coffeeWithMilk.getCost()); // Output: 1.5 ``` 在此範例中,「CoffeeDecorator」類別包裝了基本「Coffee」物件並新增了附加功能。它有一個「getCost」方法,透過將基礎咖啡的成本與 0.5 的附加成本相結合來計算總成本。 在使用部分,建立了「Coffee」類別的「myCoffee」實例。然後,實例化「CoffeeDecorator」類別的「coffeeWithMilk」實例,並將「myCoffee」作為參數傳遞。當呼叫“coffeeWithMilk.getCost()”時,它會返回咖啡的總成本以及裝飾器加入的成本,從而得到 1.5 的輸出。此範例說明了裝飾器模式如何透過動態新增或修改物件的屬性或方法來擴展物件的功能。 **立面圖案** 外觀模式為複雜子系統提供了一個簡化的接口,充當隱藏底層實現細節的前端接口。它透過提供高級接口,提供了一種與複雜系統互動的便捷方式。 ``` // Implementation example of the Facade Pattern class SubsystemA { operationA() { console.log("Subsystem A operation."); } } class SubsystemB { operationB() { console.log("Subsystem B operation."); } } class Facade { constructor() { this.subsystemA = new SubsystemA(); this.subsystemB = new SubsystemB(); } operation() { this.subsystemA.operationA(); this.subsystemB.operationB(); } } const facade = new Facade(); facade.operation(); // Output: "Subsystem A operation." "Subsystem B operation." ``` 在此範例中,程式碼由三個類別組成:「SubsystemA」、「SubsystemB」和「Facade」。 `SubsystemA` 和 `SubsystemB` 類別代表獨立的子系統,並具有各自的 `operationA` 和 `operationB` 方法。 「Facade」類別作為一個簡化的接口,聚合了子系統的功能。 在使用部分,建立了“Facade”類別的“facade”實例。呼叫「facade.operation()」會觸發「SubsystemA」中的「operationA」和「SubsystemB」中的「operationB」的執行。結果,輸出顯示“子系統 A 操作”。接下來是「子系統 B 操作」。這展示了外觀模式如何提供統一且簡化的介面來與複雜的子系統交互,抽像出它們的複雜性並使它們更易於使用。 **適配器模式** 適配器模式是一種結構設計模式,它允許具有不相容介面的物件透過充當它們之間的橋樑來進行協作。它提供了一種將一個物件的介面轉換為客戶期望的另一個介面的方法。 ``` // Implementation class LegacyPrinter { printLegacy(text) { console.log(`Legacy Printing: ${text}`); } } // Target interface class Printer { print(text) {} } // Adapter class PrinterAdapter extends Printer { constructor() { super(); this.legacyPrinter = new LegacyPrinter(); } print(text) { this.legacyPrinter.printLegacy(text); } } // Usage const printer = new PrinterAdapter(); printer.print("Hello, World!"); // Output: "Legacy Printing: Hello, World!" ``` 在此程式碼中,適配器模式用於彌合「LegacyPrinter」類別和所需的「Printer」介面之間的差距。 `PrinterAdapter` 擴展了 `Printer` 類,並在內部利用 `LegacyPrinter` 來適配 `print` 方法。當呼叫 printer.print("Hello, World!")` 時,它會有效地觸發舊版列印功能,並輸出「Legacy Printing: Hello, World!」。這展示了適配器模式如何透過提供標準化介面來整合不相容的元件。 **橋樑圖案** 橋接模式是一種結構設計模式,它將系統的抽象和實現分開,允許系統獨立發展。它透過使用介面或抽象類別在兩者之間引入了橋樑。下面是一個範例程式碼片段來說明橋接模式: ``` // Example class Shape { constructor(color) { this.color = color; } draw() {} } // Concrete Abstractions class Circle extends Shape { draw() { console.log(`Drawing a ${this.color} circle`); } } class Square extends Shape { draw() { console.log(`Drawing a ${this.color} square`); } } // Implementor class Color { getColor() {} } // Concrete Implementors class RedColor extends Color { getColor() { return "red"; } } class BlueColor extends Color { getColor() { return "blue"; } } // Usage const redCircle = new Circle(new RedColor()); redCircle.draw(); // Output: "Drawing a red circle" const blueSquare = new Square(new BlueColor()); blueSquare.draw(); // Output: "Drawing a blue square" ``` 在此範例中,我們有由 Shape 類別表示的抽象,它具有顏色屬性和繪製方法。具體抽象(圓形和方形)繼承自 Shape 類別並實現其特定的繪製行為。 「Implementor」由 Color 類別表示,該類別聲明了「getColor」方法。具體的「Implementors」、「RedColor」和「BlueColor」繼承自 Color 類別並提供各自的顏色實作。 在使用部分,我們建立具體抽象的實例,傳遞適當的具體實現者物件。這允許抽象化將與顏色相關的功能委託給實現者。當我們呼叫draw方法時,它會從Implementor存取顏色並相應地執行繪圖操作。 **複合模式** 組合模式是一種結構設計模式,可讓您統一處理單一物件和物件組合。它使您能夠建立層次結構,其中每個元素都可以被視為單個物件或物件集合。此模式使用通用介面來表示單一物件(葉節點)和組合(複合節點),允許客戶端與它們統一互動。 ``` // Implementation class Employee { constructor(name) { this.name = name; } print() { console.log(`Employee: ${this.name}`); } } // Composite class Manager extends Employee { constructor(name) { super(name); this.employees = []; } add(employee) { this.employees.push(employee); } remove(employee) { const index = this.employees.indexOf(employee); if (index !== -1) { this.employees.splice(index, 1); } } print() { console.log(`Manager: ${this.name}`); for (const employee of this.employees) { employee.print(); } } } // Usage const john = new Employee("John Doe"); const jane = new Employee("Jane Smith"); const mary = new Manager("Mary Johnson"); mary.add(john); mary.add(jane); const peter = new Employee("Peter Brown"); const bob = new Manager("Bob Williams"); bob.add(peter); bob.add(mary); bob.print(); ``` 在此範例中,我們有 Component 類別 Employee,它代表個別員工。 Composite 類 Manager 擴展了 Employee 類,並且可以包含員工的集合。它提供了在集合中新增和刪除員工的方法,並重寫 print 方法以顯示經理的姓名及其下的員工。 在使用部分,我們建立一個複合層次結構,其中 Manager 物件可以包含單一員工 (Employee) 和其他經理 (Manager)。我們將員工加入經理中,建構了一個層次結構。最後,我們呼叫頂級經理的 print 方法,該方法遞歸地列印層次結構,顯示經理及其各自的員工。 - **行為模式** 行為模式關注物件之間的互動和職責分配。它們為物件之間的通訊、協調和協作提供解決方案。以下是行為模式的類型。 - 觀察者模式 - 策略模式 - 命令模式 - 迭代器模式 - 調解者模式 **觀察者模式** 觀察者模式在物件之間建立一對多關係,其中多個觀察者會收到主體狀態變化的通知。它支援物件之間的鬆散耦合並促進事件驅動的通訊。 ``` // Implementation example of the Observer Pattern class Subject { constructor() { this.observers = []; } addObserver(observer) { this.observers.push(observer); } removeObserver(observer) { const index = this.observers.indexOf(observer); if (index !== -1) { this.observers.splice(index, 1); } } notifyObservers() { this.observers.forEach((observer) => observer.update()); } } class Observer { update() { console.log("Observer is notified of changes."); } } const subject = new Subject(); const observer1 = new Observer(); const observer2 = new Observer(); subject.addObserver(observer1); subject.addObserver(observer2); subject.notifyObservers(); // Output: "Observer is notified of changes." "Observer is notified of changes." ``` 在此範例中,「Subject」類別表示一個主題,它維護觀察者清單並提供新增、刪除和通知觀察者的方法。 「Observer」類別透過其「update」方法定義觀察者的行為。在使用部分,建立了「Subject」類別的「subject」實例。也使用“addObserver”方法建立兩個“observer”實例並將其新增至主題。 當呼叫“subject.notifyObservers()”時,它會觸發每個觀察者的“update”方法。結果,輸出「觀察者收到更改通知」。被記錄兩次,顯示觀察者已被告知主題的變化。 **策略模式** 策略模式可讓您將可互換的演算法封裝在單獨的策略物件中。它支援在執行時動態選擇演算法,從而提高靈活性和可擴展性。 ``` // Implementation example of the Strategy Pattern class Context { constructor(strategy) { this.strategy = strategy; } executeStrategy() { this.strategy.execute(); } } class ConcreteStrategyA { execute() { console.log("Strategy A is executed."); } } class ConcreteStrategyB { execute() { console.log("Strategy B is executed."); } } const contextA = new Context(new ConcreteStrategyA()); contextA.executeStrategy(); // Output: "Strategy A is executed." const contextB = new Context(new ConcreteStrategyB()); contextB.executeStrategy(); // Output: "Strategy B is executed." ``` 在此範例中,「Context」類別表示封裝不同策略的上下文,具有「strategy」屬性和「executeStrategy」方法。有兩個特定策略類,“ConcreteStrategyA”和“ConcreteStrategyB”,每個類別都有自己的“execute”方法來輸出特定訊息。 在使用部分,使用“ConcreteStrategyA”作為策略來建立“Context”類別的“contextA”實例。呼叫 `contextA.executeStrategy()` 會呼叫 `ConcreteStrategyA` 的 `execute` 方法,導致輸出「策略 A 已執行」。類似地,以「ConcreteStrategyB」為策略建立「contextB」實例,呼叫「contextB.executeStrategy()」會觸發「ConcreteStrategyB」的「execute」方法,從而輸出「策略 B 已執行」。這演示了策略模式如何透過將行為封裝在不同的策略物件中來允許在執行時動態選擇行為。 **命令模式** 命令模式將請求封裝為物件,允許您使用不同的請求對客戶端進行參數化、對請求進行排隊或記錄請求,並支援撤銷操作。它將請求的發送者與接收者解耦,從而促進鬆散耦合和靈活性。 ``` // Implementation class Receiver { execute() { console.log("Receiver executes the command."); } } class Command { constructor(receiver) { this.receiver = receiver; } execute() { this.receiver.execute(); } } class Invoker { setCommand(command) { this.command = command; } executeCommand() { this.command.execute(); } } const receiver = new Receiver(); const command = new Command(receiver); const invoker = new Invoker(); invoker.setCommand(command); invoker.executeCommand(); // Output: "Receiver executes the command." ``` 在此範例中,「Receiver」類別在呼叫時執行命令,「Command」類別封裝命令並將執行委託給接收者。 `Invoker` 類別設定並執行命令。在使用部分,建立了接收者、命令和呼叫者。此指令是為呼叫者設定的,呼叫「invoker.executeCommand()」會執行該指令,從而產生輸出「接收者執行該指令」。 **迭代器模式** 迭代器模式是一種行為設計模式,它提供了一種順序存取聚合物件的元素而不暴露其底層表示的方法。它允許您以統一的方式遍歷物件集合,而不管集合的具體實現如何。該模式將遍歷邏輯與集合分開,從而促進了一種乾淨而靈活的方法來迭代元素。 ``` // Implementation class Collection { constructor() { this.items = []; } addItem(item) { this.items.push(item); } createIterator() {} } // Concrete Aggregate class ConcreteCollection extends Collection { createIterator() { return new ConcreteIterator(this); } } // Iterator class Iterator { constructor(collection) { this.collection = collection; this.index = 0; } hasNext() {} next() {} } // Concrete Iterator class ConcreteIterator extends Iterator { hasNext() { return this.index < this.collection.items.length; } next() { return this.collection.items[this.index++]; } } // Usage const collection = new ConcreteCollection(); collection.addItem("Item 1"); collection.addItem("Item 2"); collection.addItem("Item 3"); const iterator = collection.createIterator(); while (iterator.hasNext()) { console.log(iterator.next()); } ``` 在此程式碼中,我們有由 Collection 類別表示的 Aggregate,它定義了用於建立迭代器物件的介面。具體聚合「ConcreteCollection」擴展了 Collection 類別並提供了迭代器建立的具體實作。 Iterator 由 Iterator 類別表示,它定義了存取和遍歷元素的介面。具體迭代器“ConcreteIterator”擴展了迭代器類別並提供了迭代邏輯的具體實作。在使用部分,我們建立一個 Concrete Aggregate 的實例“ConcreteCollection”,並向其中新增專案。然後我們使用 createIterator 方法建立一個迭代器。透過使用迭代器的“hasNext”和 next 方法,我們迭代集合併列印每個專案。 **調解者模式** 中介者模式透過引入充當協調物件之間互動的中心樞紐的中介者物件來簡化物件溝通。它封裝了通訊邏輯,並為物件提供了註冊、發送和接收訊息的方法。 ``` // Implementation class Mediator { constructor() { this.colleague1 = null; this.colleague2 = null; } setColleague1(colleague) { this.colleague1 = colleague; } setColleague2(colleague) { this.colleague2 = colleague; } notifyColleague1(message) { this.colleague1.receive(message); } notifyColleague2(message) { this.colleague2.receive(message); } } class Colleague { constructor(mediator) { this.mediator = mediator; } send(message) { // Send a message to the mediator this.mediator.notifyColleague2(message); } receive(message) { console.log(`Received message: ${message}`); } } // Usage const mediator = new Mediator(); const colleague1 = new Colleague(mediator); const colleague2 = new Colleague(mediator); mediator.setColleague1(colleague1); mediator.setColleague2(colleague2); colleague1.send("Hello Colleague 2!"); // Output: "Received message: Hello Colleague 2!" ``` 在此範例中,我們有一個 Mediator 類,它充當兩個 Colleague 物件之間的中介。中介者保存對同事的引用並提供在他們之間發送訊息的方法。 每個Colleague物件都有一個對中介者的引用,並且可以透過通知中介者來發送訊息。調解員又將訊息轉發給適當的同事。在這種情況下,同事 1 會向同事 2 發送訊息,後者接收並記錄該訊息。 ### 結論 我們探索了 JavaScript 中的一系列基本設計模式,包括建立模式、結構模式和行為模式。建立模式使我們能夠以靈活且高效的方式建立物件。結構模式有助於器官的靈活性和可擴展性。行為模式支援 JavaScript 物件之間的有效溝通和互動。透過利用這些設計模式,JavaScript 開發人員可以提高程式碼的可重複使用性、可維護性和整體系統效能。有了這些知識,我們就可以建立健壯且高效的 JavaScript 應用程式,以滿足現代軟體開發的需求。 --- 原文出處:https://dev.to/topefasasi/js-design-patterns-a-comprehensive-guide-h3m

JavaScript 框架 - 邁向 2024 年

我不是第一個這麼說的人,但我還是要說,2023 年對 JavaScript 框架來說是個不平凡的一年。我們一直在關注的新技術最終顯示出它們可以交付,而舊框架正在復興,如果您不注意,您可能會錯過一個相當重大的轉變。 我預計 2024 年將繼續出現更大的全面變化。這次不是新技術,而是精細化。既然基礎已經存在,那麼還有很多事情要做。 -------------------- ## 伺服器優先 如果讓我為過去幾年選擇一個主題,那就是這個。這一直是爭論的焦點,但不可否認。幾年前,每個人都在談論漸進式 Web 應用程式和離線應用程式。但那個對話框幾乎消失了。 相反,我們會受到 HTMX 的敏銳智慧的影響,解釋為什麼 JavaScript 只是一個錯誤。 Astro 毫無歉意地接管了內容網站的開發。甚至 React Core 團隊也接受了 React Server Components 的伺服器簡單性,Dan Abramov 的演講令人信服地表達了這一點,該演講探討瞭如果 React 始終是伺服器優先會怎樣。 https://www.youtube.com/watch?v=zMf_xeGPn6s 那麼我們的單頁應用程式親愛的在這麼短的時間內發生了什麼?它是否仍然存在,還是我們生活在多頁面應用程式和僅伺服器渲染 HTML 的時代? ------------------ ## 回顧 2023 年 去年,我寫了一篇非常類似的文章,探討了新的一年 JavaScript 框架的趨勢,我認為這是一個很好的起點。 https://dev.to/this-is-learning/javascript-frameworks-heading-into-2023-nln 該文章中確定的三大技術趨勢成為去年討論的重要組成部分。 ### 訊號無所不在 從 2022 年底開始,Preact 和 Qwik 緊跟著 SolidJS 和 Vue 的腳步,採用這些 Reactive 原語,這種勢頭只會持續到 2023 年。 二月份,Angular 團隊宣布採用。這一訊息震驚了社群媒體。不僅。這是 Angular 的存在發生非常顯著變化的幾個因素之一。有人甚至稱之為「角度復興」。這是過去幾年我們第一次看到 React 團隊加入這場爭論,因為真正被問到的問題是「訊號什麼時候出現在 React 中?」。 我在下面的文章中寫了這個問題的更長的答案(以及在評論中與丹·阿布拉莫夫的討論)。 https://dev.to/this-is-learning/react-vs-signals-10-years-later-3k71 但簡短的回答是,訊號(至少作為 API)並不是他們感興趣的東西,而他們備受期待的「忘記」編譯器將扮演類似的角色。 但訊號傳播並沒有就此結束。 Lit 是 Google 的 Web 元件框架,推出了[Lit 3,具有第一方訊號支援](https://lit.dev/blog/2023-10-10-lit-3.0/#preact-signals-integration)。 Rich Harris 公佈了 Svelte 的未來,[他們新的基於訊號的「Runes」](https://svelte.dev/blog/runes),將成為即將推出的 Svelte 5 中反應性的主要來源。 2023 年結束訊號是大多數前端 JavaScript 框架的主要部分。 ### 混合路由 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mdtlafe81eo4jchqx37w.png) 去年,基於伺服器的路由得到了加強並發揮了新的作用。從 2022 年底開始,到今年,我們看到人們已經習慣了這種範式轉變,例如 React Server Components 和 Astro 的 View Transition API 整合。 前提是初始頁面載入後的伺服器渲染不應阻止客戶端導航,且客戶端導航不應意味著我們需要發送所有 JavaScript 來渲染可以靜態伺服器渲染的頁面部分。 值得注意的是,並非所有解決方案都是等效的,而且這個領域仍在建設中。我們正在進入一個新的空間,它不完全是單頁應用程式,也不完全是傳統的多頁面網站。需要進行新的權衡和新的理解。我們還沒有完成對陷阱的探索。 ### 邊緣網路:最後的前沿 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bss8a8hwf3qbozvvq9a6.jpg) 邊緣功能似乎是那些明顯的勝利之一。將伺服器移至更靠近最終用戶的位置,可以大幅減少延遲。使用更輕的執行時間可以大幅減少冷啟動時間。我們終於可以提供我們一直夢想的網路體驗。以靜態的速度實現動態。 好吧,如果有什麼不同的話,2023 年是成長的陣痛和邊緣的一年。我們開始非常熱情。畢竟,Cloudflare 發布了邊緣資料庫,我們最喜歡的所有提供者都開始提供邊緣功能,而我們最喜歡的框架正在加入開箱即用的支援。提供者成立了一個 WinterCG 委員會來討論平台標準化問題。未來就在這裡。 我們最終認識到,即使在這些邊緣功能中,某些 Node API 也是必不可少的。您可以感謝或討厭 Next 和 Vercel 將“AsyncLocalStorage”推送到每個執行時,但我們需要它。 我們也意識到邊緣資料庫永遠無法滿足所有應用程式。即使使用串流媒體,伺服器瀑布也是真實且有影響力的。是的,即使使用 React Server 元件也是如此。 但這確實實現了我去年提出的目標,透過分散式部署進行整體創作。我們看到伺服器函數(`server$`、`use server`),甚至像 Worker Functions 這樣的變體在今年年初出現,表明我們可以分發我們部署 API 的方式,並被 Solid、Qwik 和 Next 採用。 到年底 [Next 14 發布了新的實驗性部分預渲染](https://nextjs.org/blog/next-14),它允許單一請求從邊緣提供靜態內容,同時代理到伺服器-less 靠近資料庫的函數全部被串流傳輸,以提供類似Edge 的體驗,而無需在那裡部署整個應用程式。看到一些獨創性提供了兩全其美的解決方案真是太棒了。 ---------------- ## 展望 2024 年 ### 訊號年 我知道我已經在一篇文章中充分討論了信號,但真正的回報還沒有發生。我們在 JavaScript 中使用細粒度的類似 Signal 的原語已有 15 年了,那麼為什麼現在呢? 這不僅僅是關於擁有它們,而是關於你如何使用它們。 Vue 多年來一直在隱藏這些原語,React 和 MobX 也是如此,但這幾乎沒有觸及事情的發展方向。那就是細粒度渲染。 SolidJS 所普及的內容,現在以 Vue Vapor 的形式進入 Vue,以及 Svelte 5 中的 Svelte。這些只是已經宣布的內容。 我希望其他採用訊號的人能夠更自然地將它們融入框架中,以便更好地從中受益。 這個領域的潛力令人興奮,致力於將 Signals 引入瀏覽器的 TC-39 提案的小組包括來自每個主要 JavaScript 框架的代表,而這個小組並不總是與標準密切相關。 ### 基礎設施主導的發展 既然伺服器端渲染框架已經打了一針強心劑,那麼下一個合乎邏輯的地方就是繼續考慮最大限度地利用這項新功能為我們提供的功能。標準的製定很慢,WinterCG 也需要一些時間,但這不會阻止這裡的發展。 為了實現差異化,我預期框架和基礎設施供應商都會面臨壓力,要求他們提供只能在特定平台上運作的獨特功能。雖然 2023 年各個提供者都在推動平等,以提供超出其基本靜態和功能託管的類似功能(例如鍵值存儲 Blob),但我只看到這裡提供獨特價值的競爭正在升溫。 框架在這方面的作用是保持一致的創作體驗和思考模型,同時找到利用呈現給我們的新能力的方法。這與 2000 年代末的瀏覽器戰爭沒有什麼不同,而且未來還會有很多事情發生。 ### 人工智慧 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sma4crnqjxbx89hhh7r3.jpg) 去年從框架的角度談論人工智慧還為時過早。明年也可能如此。但它就在眼前。程式碼遷移和生成工具都是很棒的想法,但它們遇到了我們多年來使用視覺化無程式碼或低程式碼編輯器所遇到的相同問題。人機界麵點仍然至關重要。畢竟,程式碼是有生命的東西。它會隨著時間的推移而增長和維持。 在過去的一年裡,與其他框架作者交談時,我們發現它吸引了我們周圍的人,但還沒有達到明確我們在其中的角色的程度。但這種情況正在改變。 是的,人工智慧正在回答一個永恆的問題:為什麼你的應用程式速度很慢。 對開發人員工具的影響是一回事。但我們也看到我們的框架中內建即時性的潛力越來越大。我也不僅僅指用於持久後端的 Websockets。元框架中的 API 已經從簡單的 JSON 發展到使用 SolidStart、Qwik 和 Next 中的「伺服器功能」完全流式跨網路 JavaScript 執行。不難想像生成技術即時建立使用者介面。 -------------------------- ## 結論 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pf0pc8fhlor9xnou9r8b.jpg) 2024 年可能會繼續我們過去幾年看到的成熟趨勢。從 2020-22 年,我們看到了許多新的 JavaScript(和 WASM)框架(Qwik、Million.js、Astro、Next 13、Remix、Hydrogen、SvelteKit、SolidStart、Leptos、Dioxus、HTMX),但這還不是去年的案例。我們已經找到了方法,現在我們需要充分發揮它們的潛力。 我不確定我們是否已經成功地解決了複雜性,這對像 Astro 或 HTMX 這樣的簡化解決方案給予了大力支持。但我仍然充滿希望。 期望每個人都就「單頁應用程式」到底是什麼或何時應該使用擺在我們面前的各種選項達成一致可能有點太過分了,但這些解決方案每天都在變得更有能力實現他們設定的目標出去做。 我們所知道的網頁開發是否會改變已經不再是一個問題。即使方向還不完全明確,革命已經來臨。期望在那裡見到你。 --- 原文出處:https://dev.to/this-is-learning/javascript-frameworks-heading-into-2024-i3l

关于 JS 的一些高级用法

在学习 JavaScript中,变量、函数、类、循环、异步这些都是基础知识。这些基础知识是我们使用 JavaScript 的基础。但是,在日常的业务开发中,我们需要一些更高级的技巧来更好地解决问题。 > 通过本文你将了解到 JS 的高级知识点以及实际应用技巧,如高级数据结构和算法、函数式编程、异步编程和面向对象编程。我们会利用代码实例来让大家更好地理解这些知识点。同时,我们也会提供一些实战案例的示范和使用技巧,让你更好地将这些技术应用到实际业务中。 ## 高级数据结构和算法 ### Map 和 Set 数据结构 在 JavaScript 中,Map 数据结构通常用于存储键值对,它可以使用任意类型作为键和值。Set 数据结构用于存储唯一值的集合。 ```js // 创建Map对象 const map = new Map(); // 设置键值对 map.set("name", "Tom"); map.set("age", 20); // 获取键值对 console.log(map.get("name")); // 'Tom' console.log(map.get("age")); // 20 // 创建Set对象 const set = new Set(); // 添加元素 set.add(10); set.add(20); set.add(30); // 删除元素 set.delete(20); // 判断元素是否存在 console.log(set.has(10)); // true console.log(set.has(20)); // false ``` ### 堆、栈和队列 堆和栈是常用的内存分配方式。栈是一种后进先出的数据结构,堆是一种动态分配的内存结构。队列是一种先进先出的数据结构,它通常用于缓存和并发编程中。 ```js // 使用数组模拟堆 const arr = [1, 2, 3, 4]; arr.push(5); // 入堆 console.log(arr.pop()); // 出堆 // 使用数组模拟栈 const stack = [1, 2, 3, 4]; stack.push(5); // 入栈 console.log(stack.pop()); // 出栈 // 使用数组模拟队列 const queue = [1, 2, 3, 4]; queue.push(5); // 入队 console.log(queue.shift()); // 出队 ``` ### 深度优先搜索和广度优先搜索 深度优先搜索(DFS)和广度优先搜索(BFS)是常用的遍历算法。DFS 通常用于解决深度问题,BFS 适用于宽度问题。 ```js // 深度优先遍历 function dfs(node) { if (node == null) return; console.log(node.value); dfs(node.left); dfs(node.right); } // 广度优先遍历 function bfs(node) { const queue = [node]; while (queue.length) { const curr = queue.shift(); console.log(curr.value); if (curr.left) queue.push(curr.left); if (curr.right) queue.push(curr.right); } } ``` ### 常用算法 常用的算法有排序、搜索、查找等。 ```js // 排序算法:快速排序使用分治思想,通过把数组分成较小的块来排序。 function quickSort(arr) { if (arr.length < 2) { return arr; } let pivot = arr[0]; let left = []; let right = []; for (let i = 1; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return [...quickSort(left), pivot, ...quickSort(right)]; } // 查找算法: function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } ``` ## 函数式编程 ### 高阶函数和柯里化 高阶函数和柯里化是函数式编程中的常见概念,它们可以让我们创建更加抽象、灵活的函数。 ```js // 高阶函数 function higherOrderFunction(func) { return function (num) { return func(num); }; } function double(num) { return num * 2; } const doubleFunc = higherOrderFunction(double); console.log(doubleFunc(10)); // 20 // 柯里化 function curry(func) { return function curried(...args) { if (args.length >= func.length) { return func.apply(this, args); } else { return function (...args2) { return curried.apply(this, [...args, ...args2]); }; } }; } function sum(a, b, c) { return a + b + c; } const curriedSum = curry(sum); console.log(curriedSum(1)(2)(3)); // 6 ``` ### 闭包和作用域 闭包和作用域是 JavaScript 中比较常见的概念。闭包可以让我们维护函数内的状态,作用域则决定了变量的可见范围。 ```js // 闭包 function closure() { let i = 0; return function () { return ++i; }; } const func = closure(); console.log(func()); // 1 console.log(func()); // 2 // 作用域 let a = 10; function foo() { let a = 20; console.log(a); // 20 } foo(); console.log(a); // 10 ``` ### 函数式编程中的常见模式 函数式编程中有很多常见的模式,如 map、filter、reduce 等。 ```js // map const arr = [1, 2, 3]; const mapArr = arr.map((item) => item * 2); console.log(mapArr); // [2, 4, 6] // filter const filterArr = arr.filter((item) => item > 1); console.log(filterArr); // [2, 3] // reduce const reduceArr = arr.reduce((sum, curr) => sum + curr, 0); console.log(reduceArr); // 6 异步编程 Promise和async/await Promise和async/await是常见的异步编程方式,它们可以让我们更好地处理异步编程中的问题。 // Promise function promise() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('done'); }, 1000); }); } promise().then((result) => console.log(result)); // 'done' // async/await async function asyncFunc() { const result = await promise(); console.log(result); } asyncFunc(); // 'done' ``` ### 事件循环和 EventEmitter 事件循环和 EventEmitter 用于处理异步事件,它们可以让我们更好地处理事件流。 ```js // 事件循环 console.log("start"); setTimeout(() => { console.log("setTimeout"); }, 0); Promise.resolve().then(() => console.log("promise")); console.log("end"); // EventEmitter const { EventEmitter } = require("events"); const emitter = new EventEmitter(); emitter.on("doSomething", (arg1, arg2) => { console.log(`${arg1} ${arg2}`); }); emitter.emit("doSomething", "Hello", "World"); // 'Hello World' ``` ### Web Worker Web Worker 可以让我们将长时间运行的任务移出主线程,以避免阻塞 UI。 ```js // 主线程 const worker = new Worker("worker.js"); worker.onmessage = (event) => { console.log(event.data); }; worker.postMessage("start"); // worker.js self.onmessage = (event) => { const result = longCalculation(event.data); self.postMessage(result); }; ``` ## 面向对象编程 ### 类和继承 JavaScript 中的类和继承与其他面向对象编程语言类似。 ```js // 类 class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Cat extends Animal { constructor(name, breed) { super(name); this.breed = breed; } speak() { console.log(`${this.name} meows.`); } get description() { return `${this.name} is a ${this.breed} cat.`; } set nickname(nick) { this.name = nick; } } const cat = new Cat("Fluffy", "Persian"); cat.speak(); // 'Fluffy meows.' console.log(cat.description); // 'Fluffy is a Persian cat.' cat.nickname = "Fuffy"; console.log(cat.name); // 'Fuffy' ``` ### Encapsulation、Inheritance、Polymorphism(封装、继承、多态) 封装、继承、多态是面向对象编程中的重要概念。 ```js // 封装 class Person { constructor(name) { this._name = name; } get name() { return this._name.toUpperCase(); } set name(newName) { this._name = newName; } } const person = new Person("John"); console.log(person.name); // 'JOHN' person.name = "Lisa"; console.log(person.name); // 'LISA' // 继承 class Shape { constructor(color) { this.color = color; } draw() { console.log("Drawing a shape..."); } } class Circle extends Shape { constructor(color, radius) { super(color); this.radius = radius; } draw() { console.log(`Drawing a ${this.color} circle with radius ${this.radius}.`); } } const circle = new Circle("red", 10); circle.draw(); // 'Drawing a red circle with radius 10.' // 多态 function drawShape(shape) { shape.draw(); } drawShape(new Shape("blue")); // 'Drawing a shape...' drawShape(new Circle("green", 20)); // 'Drawing a green circle with radius 20.' ``` ## 总结和实战 在本文中,我们介绍了一些 JavaScript 的高级知识点,如高级数据结构和算法、函数式编程、异步编程和面向对象编程。我们还提供了一些代码示例和实战案例,让大家更好地理解和掌握这些技术。 ### 通过 Promise.all 实现并发请求 ```js function fetchData(urls) { const promises = urls.map((url) => fetch(url)); return Promise.all(promises).then((responses) => Promise.all( responses.map((response) => { if (!response.ok) throw new Error(response.statusText); return response.json(); }) ) ); } ``` ### 使用 async/await 实现异步调用 ```js async function getData(url) { const response = await fetch(url); if (!response.ok) throw new Error(response.statusText); const data = await response.json(); return data; } ``` ### 在面向对象编程中使用工厂模式 ```js class Product { constructor(name, price) { this.name = name; this.price = price; } } class ProductFactory { createProduct(name, price) { return new Product(name, price); } } const productFactory = new ProductFactory(); const product = productFactory.createProduct("Apple", 1); console.log(product.name); // 'Apple' console.log(product.price); // 1 ``` 本文结束,感谢阅读

📚 前 1% 的 React 開發者使用的 8 個儲存庫 🏆

你好👋 今天,讓我們來看看**前 1% 的開發人員使用**的 8 個 React 儲存庫(以及那些您可能從未聽說過的儲存庫)。 準備好? ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yehweju0i54ov2n6bwt.gif) --- # 我們如何找到前 1% 的開發人員使用的儲存庫? 🔦 我們如何找到最好的開發人員使用的東西背後的故事植根於大量的資料探勘和一些重要的建模。 現在,在 Quine,我們根據開發人員的**[DevRank](https://docs.quine.sh/for-developers/devrank)** 對開發人員進行排名。 簡單來說,DevRank 使用 [Google 的 PageRank 演算法](https://en.wikipedia.org/wiki/PageRank) 根據開發人員對開源儲存庫的貢獻來衡量開發人員在開源領域的重要性。 為了建立此列表,我們查看了前 1% 已加星號的儲存庫。 🌟 然後,我們計算了前 1% 的開發者會為回購加註星標的可能性,與後 50% 的開發者不支持的可能性進行比較。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miugcnqpataix1fsq6hb.png) 最後,經過一番挑選,我們找到了以下 8 個儲存庫。 :向下點: 當您想要建立很酷的網頁應用程式時,這些儲存庫將特別有用。** 如果您有興趣建立小型應用程式,並且喜歡應用人工智慧方面,我們建議您查看 Creator Quests,這是一項**開源挑戰,獎勵開發人員使用 ChatGPT、Claude、Gemini 建立酷炫的 GenerativeAI 應用程式**和更多。 :upside_down_face: 💰 最新的 Creator Quest 挑戰您使用生成式 AI 建立開發人員工具。要參與,只需註冊 [Quine](https://quine.sh/?utm_source=devto&utm_campaign=best_react_repos) 並前往 _Quests_。 **目前獎金池為$2028**,並且隨著更多參與者的加入,獎金池將會增加!點擊下面的圖片並嘗試! ⬇️ [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/akiuhk62zctvf3b9gilx.png)](https://quine.sh/?utm_source=devto&utm_campaign=best_react_repos) --- # jsxstyle/jsxstyle **不再有 JS 到 CSS 的跳躍** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h75mskqja5bcwst05e93.png)](https://github.com/jsxstyle/jsxstyle) **為什麼要關心?** 在 Web 開發中,使用 React 或 Preact,您必須設定元件的樣式(如按鈕、選單等)。傳統上,這是使用單獨的 CSS 檔案或複雜的樣式系統來完成的,這可能非常耗時且管理起來很麻煩。 jsxstyle 可讓您直接在 JavaScript 程式碼中以及元件中定義樣式,從而簡化了此過程。換句話說,這意味著您不再需要在 JS 和 CSS 檔案之間跳躍。 **設定**:`npm install jsxstyle` **範例用例**:您的程式碼可以如下所示。 👇 ``` <Row padding={15}> <Block backgroundColor="#EEE" boxShadow="inset 0 0 0 1px rgba(0,0,0,0.15)" borderRadius={5} height={64} width={64} marginRight={15} backgroundSize="contain" backgroundImage="url(http://graph.facebook.com/justinbieber/picture?type=large)" /> <Col fontFamily="sans-serif" fontSize={16} lineHeight="24px"> <Block fontWeight={600}>Justin Bieber</Block> <Block fontStyle="italic">Canadian</Block> </Col> </Row> ``` [https://github.com/jsxstyle/jsxstyle](https://github.com/jsxstyle/jsxstyle) --- # 💨 alangpierce/蔗糖酶 **Babel 的超快替代品** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rk9ceq6mlw8ya0f2icb8.png)](https://github.com/alangpierce/sucrase) **為什麼你應該關心?** Babel 是 Web 開發中廣泛使用的工具,可將現代 JavaScript 程式碼轉換為舊瀏覽器可以理解的格式。 Sucrase 是 Babel 更快的替代品。 **設定**: ``` yarn add --dev sucrase # Or npm install --save-dev sucrase node -r sucrase/register main.ts ``` **用例範例**:Sucrase 可以直接從 JS 呼叫: ``` import {transform} from "sucrase"; const compiledCode = transform(code, {transforms: ["typescript", "imports"]}).code; ``` [https://github.com/alangpierce/sucrase](https://github.com/alangpierce/sucrase) --- # 🎨 woorm/折射鏡 **我為您的網頁程式碼著色,讓您的生活更輕鬆** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hzwpgi5t47o93kvcbtdq.png)](https://github.com/wooorm/refractor) **為什麼你應該關心?** Refractor 很重要,因為它允許您加入突出顯示,從而增強專案的可讀性;尤其是當您將程式碼片段新增至 Web 應用程式時。它允許您用 270 多種程式語言表達程式碼,並且在傳統的基於 HTML 的突出顯示不理想的領域(例如 CLI 表單)特別有用。 **設定**:`npm install refractor` **用例範例**: ``` import {refractor} from 'refractor' const tree = refractor.highlight('"use strict";', 'js') console.log(tree) ``` **產量**: ``` { type: 'root', children: [ { type: 'element', tagName: 'span', properties: {className: ['token', 'string']}, children: [{type: 'text', value: '"use strict"'}] }, { type: 'element', tagName: 'span', properties: {className: ['token', 'punctuation']}, children: [{type: 'text', value: ';'}] } ] } ``` [https://github.com/wooorm/refractor](https://github.com/wooorm/refractor) --- # 🐦 react-static-tweets **您在網站上加入推文的最佳選擇。** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lvul78znx84ph479fa1.png)](https://github.com/transitive-bullshit/react-static-tweets) **為什麼你應該關心?** 將推文加入到您的網站是您在許多登陸頁面上看到的一項很酷的功能。 React Static Tweets 很重要,因為它提供了一種在 Web 專案中嵌入推文的高效方法,與 Twitter 的標準嵌入方法相比,提供更快的載入時間和更好的效能。 **設定**: ``` npm install react-static-tweets static-tweets date-fns # or yarn add react-static-tweets static-tweets date-fns ``` **用例範例:** ``` import React from 'react' import { fetchTweetAst } from 'static-tweets' import { Tweet } from 'react-static-tweets' const tweetId = '1358199505280262150' export const getStaticProps = async () => { try { const tweetAst = await fetchTweetAst(tweetId) return { props: { tweetAst }, revalidate: 10 } } catch (err) { console.error('error fetching tweet', err) throw err } } export default function Example({ tweetAst }) { return <Tweet ast={tweetAst} /> } ``` [https://github.com/transitive-bullshit/react-static-tweets](https://github.com/transitive-bullshit/react-static-tweets) --- # 🖨️ preactjs/preact-render-to-string **以 HTML 形式呈現您的元件** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7djwj6w7nqwfnifc43c.png)](https://github.com/preactjs/preact-render-to-string) **為什麼要關心?** 「preact-render-to-string」是一個工具,可以幫助網站更快地載入並在搜尋引擎中更好地顯示。使用 Preact 等 JS 框架建立的網站需要一段時間才能顯示內容,因為瀏覽器必須先執行 JavaScript。此儲存庫透過將元件轉換為現成的 HTML 來完成伺服器端的繁重工作。因此,當有人造訪該網站時,即使網路速度很慢,他們也會立即看到內容。 **設定**:`npm install preact-render-to-string` **用例範例:** ``` import { render } from 'preact-render-to-string'; import { h, Component } from 'preact'; /** @jsx h */ // Classical components work class Fox extends Component { render({ name }) { return <span class="fox">{name}</span>; } } // ... and so do pure functional components: const Box = ({ type, children }) => ( <div class={`box box-${type}`}>{children}</div> ); let html = render( <Box type="open"> <Fox name="Finn" /> </Box> ); console.log(html); // <div class="box box-open"><span class="fox">Finn</span></div> ``` [https://github.com/preactjs/preact-render-to-string](https://github.com/preactjs/preact-render-to-string) --- # 🏆 自行車刮鬍/曲柄 **唯一的 JavaScript 框架** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8hp1ex1qh1sv6isksaq.png)](https://github.com/bikeshaving/crank) **為什麼要關心?** 在像 React 這樣的傳統 Web 框架中,Web 元件配置一次,僅在明確指定時才更改。它們看起來像是需要手動更新的靜態影像。 Crank.js 透過允許小部件更新自身以回應新資料來改變這一點,類似於用新新聞刷新的新聞收報機。這對於管理即時資料(例如即時體育賽事比分或產品更新)的 Web 應用程式尤其有用。 這個倉庫需要更多的人遷移到這裡才能獲得關注,但它仍然是一個非常酷的倉庫,值得關注。 👀 **設定**:`$ npm i @b9g/crank` **用例範例**: ``` import {renderer} from "@b9g/crank/dom"; function Greeting({name = "World"}) { return ( <div>Hello {name}</div> ); } renderer.render(<Greeting />, document.body); ``` [https://github.com/bikeshaving/crank](https://github.com/bikeshaving/crank) --- # 🎯 evoluhq/evolu **我是一個本地第一的人** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k15m25pi0w9pk0g54zrn.png)](https://github.com/evoluhq/evolu) **為什麼要關心?** Web 應用程式通常依賴在伺服器上儲存使用者資料,這需要持續的網路連接,並引起對隱私和資料安全的擔憂。這種基於伺服器的方法也意味著如果伺服器發生故障或公司停止運營,效能會降低,並且可能會遺失資料。 Evolu 引入了「本地優先」方法,其中資料直接儲存在使用者的裝置上。這意味著您的應用程式可以離線工作,更快地存取資料,並提供增強的隱私和安全性。如果您正在建立離線 Chrome/瀏覽器應用程式,這將非常有用。 **設定**:` npm install @evolu/react` 要開始使用它,您可以在[此處](https://www.evolu.dev/docs/quickstart)找到這個很棒的指南。 [https://github.com/evoluhq/evolu](https://github.com/evoluhq/evolu) --- # 📸 笑話社群/快照差異 **我比較你們的元件並突出顯示差異** [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hy76comkwkqkt0d5qn8z.png)](https://github.com/jest-community/snapshot-diff) **為什麼要關心?** 在測試 React 元件或其他 JavaScript 值時,開發人員通常會比較整個狀態或輸出。這意味著處理大量資料,查找特定變更就像大海撈針一樣。 Snapshot-diff 是重點比較工具,可讓您取得元件的兩種不同狀態(或任兩個 JavaScript 值)並直接比較它們,僅將差異突出顯示。 這對於測試 React 元件特別有幫助,因為它可以準確指出兩種狀態之間發生的變化,從而更容易辨識和理解程式碼變更的影響。 **設定**:`yarn add --dev snapshot-diff` **範例用例:** 預設笑話匹配器 ``` const snapshotDiff = require('snapshot-diff'); test('snapshot difference between 2 strings', () => { expect(snapshotDiff(a, b)).toMatchSnapshot(); }); const React = require('react'); const Component = require('./Component'); test('snapshot difference between 2 React components state', () => { expect( snapshotDiff(<Component test="say" />, <Component test="my name" />) ).toMatchSnapshot(); }); ``` [https://github.com/jest-community/snapshot-diff](https://github.com/jest-community/snapshot-diff) --- **我希望這些發現對您有價值,並將有助於建立更強大的 React 工具包!⚒️** 如果您今天想利用這些工具來獲得獎勵,我們剛剛發起了一項使用生成式人工智慧建立開發人員工具的挑戰。 如果對此有興趣,請登入 [Quine](https://quine.sh/?utm_source=devto&utm_campaign=best_react_repos) 並發現任務! 💰 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5drisgbolxfnzfvtwzw.gif) 最後,請**考慮透過加星號來支持這些專案。 ⭐️** PS:我們與他們沒有任何關係。我們只是認為偉大的專案值得高度認可。 下週見, 您的開發夥伴💚 巴普 --- 原文出處:https://dev.to/quine/8-repos-used-by-the-top-1-of-react-devs-2758

🎉像專業人士一樣監控您的 Javascript 應用程式🧙‍♂️💫

## **簡介** 在本教程中,您將學習如何使用**現代工具**和**最佳實踐**來監控您的Javascript應用程式。 探索分散式追蹤的力量,並了解如何無縫整合和利用 Odigos 和 Jaeger 等工具來增強您的監控能力。 **您將學到什麼:✨** - 如何在 Javascript 中建立微服務🐜。 - 為微服務設定 Docker 容器📦。 - 配置 Kubernetes ☸️ 以管理微服務。 - 整合追蹤後端以可視化追蹤🔍。 您準備好成為監控 JS 應用程式的**專家**了嗎? 😍 說**是的,先生!**。 我聽不到你說話。大聲點說。 🙉 ![大聲點 GIF](https://media.giphy.com/media/8m5dizh7ghyEPIWIx1/giphy.gif) *** ## **讓我們設定一下 🦄** > 🚨 在部落格的這一部分中,我們將建立一個虛擬的 JavaScript 微服務應用程式並將其部署在本地 Kubernetes 上。如果您已經有一個並且正在跟進,請隨意跳過這一部分。 為您的應用程式建立初始資料夾結構,如下所示。 👇🏻 ``` mkdir microservices-demo cd microservices-demo mkdir src cd src ``` ### **設定伺服器** 🖥️ > 👀 出於演示目的,我將建立兩個相互通信的微服務,最終我們可以使用它來視覺化分散式追蹤。 - **建置與 Dockerize 微服務 1** 在「/src」資料夾中,建立一個新資料夾「/microservice-1」。在資料夾內初始化 **NodeJS** 專案並安裝所需的依賴項。 ``` mkdir microservice-1 cd microservice-1 npm init -y npm install --save express node-fetch ``` 建立一個新檔案“index.js”並新增以下程式碼: ``` // 👇🏻/src/microservice-1/index.js const express = require("express"); const fetch = require("node-fetch") const app = express(); const PORT = 3001; app.use(express.json()); app.get("/", async (req, res) => { try { const response = await fetch("http://microservice2:8081/api/data"); const data = await response.json(); res.json({ data: "Microservice 2 data received in Microservice 1", microservice2Data: data, }); } catch (error) { console.error(error.message); res.status(500).json({ error: "Internal Server Error" }); } }); app.listen(PORT, () => { console.log(`Microservice 1 listening on port ${PORT}`); }); ``` 伺服器正在偵聽連接埠“3001”,並且在對“/”發出請求時,我們從“microservice2”請求資料並將回應作為 JSON 物件返回。 📦 現在,是時候對這個微服務進行 docker 化了。在“/microservice-1”資料夾中建立一個新的“Dockerfile”並新增以下程式碼: ``` // 👇🏻/src/microservice-1/Dockerfile FROM node:18 # Use /usr/src/app as the working directory WORKDIR /usr/src/app # Copy package files and install production dependencies COPY --chown=node:node package*.json /usr/src/app RUN npm install --production # Copy the rest of the files COPY --chown=node:node . /usr/src/app/ # Switch to the user node with limited permissions USER node # Expose the application port EXPOSE 3001 # Set the default command to run the application CMD ["node", "index.js"] ``` 將我們不想推送到容器的文件加入到“.dockerignore”總是很好。使用我們不想推送的檔案的名稱來建立一個“.dockerignore”檔案。 ``` // 👇🏻/src/microservice-1/.dockerignore node_modules Dockerfile ``` 最後,透過執行以下命令來建構 🏗️ docker 映像: ``` docker build -t microservice1-image:latest . ``` 現在,這就是我們第一個微服務的完整設定。 ✨ - **建置與 Dockerize 微服務 2** 我們將有一個類似於“microservice1”的設置,只是在這裡和那裡進行了一些更改。 在「/src」資料夾中,建立一個新資料夾「/microservice-2」。在該資料夾內,初始化 **NodeJS** 專案並安裝所需的依賴項。 ``` mkdir microservice-2 cd microservice-2 npm init -y npm install --save express node-fetch ``` 建立一個新檔案“index.js”並新增以下程式碼: ``` // 👇🏻/src/microservice-2/index.js const express = require("express"); const fetch = require("node-fetch") const app = express(); const PORT = 3002; app.use(express.json()); app.get("/api/data", async (req, res) => { const url = "https://jsonplaceholder.typicode.com/users"; try { const response = await fetch(url); const data = await response.json(); res.json(data); } catch (error) { console.error(error.message); res.status(500).json({ error: "Internal Server Error" }); } }); app.listen(PORT, () => { console.log(`Microservice 2 listening on port ${PORT}`); }); ``` 伺服器正在偵聽連接埠 3002,根據對“/api/data”的“GET 請求”,我們從“jsonplaceholder”獲取資料並將回應作為 JSON 物件傳回。 📦 現在,是時候對這個微服務進行 docker 化了。複製並貼上「microservice1」的整個「Dockerfile」內容,然後將連接埠從 3001 變更為 3002。 另外,新增一個「.dockerignore」檔案並包含我們在建立「microservice1」時新增的相同檔案。 最後,透過執行以下命令來建構 🏗️ Docker 映像: ``` docker build -t microservice2-image:latest . ``` 現在,這也是我們第二個微服務的完整設定。 ✨ - **設定 Kubernetes** > 確保已安裝 **[Minikube](https://github.com/kubernetes/minikube)** 透過執行以下命令建立新的本機 Kubernetes 叢集。我們在設定 Odigos 和 Jaeger 時將需要它。 **啟動 Minikube:🚀** ``` minikube start ``` 現在我們已經準備好並 Docker 化了兩個微服務,是時候設定 Kubernetes 來管理這些服務了。 在專案的根目錄下,建立一個新資料夾「/k8s/manifests」。在此資料夾中,我們將為兩個微服務新增部署和服務配置。 - **部署設定📜**:用於在 Kubernetes 叢集上實際部署容器。 - **服務配置📄**:將 Pod 暴露給叢集內部和叢集外部。 首先,我們為「microservice1」建立清單。建立一個新檔案「microservice1-deployment-service.yaml」並新增以下內容: ``` // 👇🏻/k8s/manifests/microservice1-deployment-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: microservice1 spec: selector: matchLabels: app: microservice1 template: metadata: labels: app: microservice1 spec: containers: - name: microservice1 image: microservice1-image # Make sure to set it to Never, or else it will pull from the docker hub and fail. imagePullPolicy: Never resources: limits: memory: "200Mi" cpu: "500m" ports: - containerPort: 3001 --- apiVersion: v1 kind: Service metadata: name: microservice1 labels: app: microservice1 spec: type: NodePort selector: app: microservice1 ports: - port: 8080 targetPort: 3001 nodePort: 30001 ``` 此配置部署了一個名為「microservice1」的微服務,其資源限制為 **200MB 記憶體** 🗃️ 和 **0.5 個 CPU 核心**。它透過部署在連接埠 3001 上公開微服務,並透過服務在 **NodePort** 30001 上公開微服務。 > 🤔 還記得我們用名稱「microservice1-image」建構的「Dockerfile」嗎?我們使用相同的映像來建立容器。 可透過集群內的連接埠 8080 存取它。我們假設「microservice1-image」透過「imagePullPolicy: Never」在本地可用。如果沒有到位,它將嘗試從 Docker Hub 🐋 中提取映像並失敗。 現在,讓我們為「microservice2」建立清單。建立一個名為「microservice2-deployment-service.yaml」的新檔案並新增以下內容: ``` // 👇🏻/k8s/manifests/microservice1-deployment-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: microservice2 spec: selector: matchLabels: app: microservice2 template: metadata: labels: app: microservice2 spec: containers: - name: microservice2 image: microservice2-image # Make sure to set it to Never, or else it will pull from the docker hub and fail. imagePullPolicy: Never resources: limits: memory: "200Mi" cpu: "500m" ports: - containerPort: 3002 --- apiVersion: v1 kind: Service metadata: name: microservice2 labels: app: microservice2 spec: type: NodePort selector: app: microservice2 ports: - port: 8081 targetPort: 3002 nodePort: 30002 ``` 它與“microservice1”的清單類似,只有一些更改。 👀 此配置部署一個名為「microservice2」的微服務,並透過部署在連接埠 3002 上將其內部公開,並透過服務在 **NodePort** 30002 上將其外部公開。 可透過叢集內的連接埠 8081 進行存取,假設「microservice2-image」可透過「imagePullPolicy: Never」在本地使用。 全部完成後,請確保套用這些設定並使用這些服務啟動 Kubernetes 叢集。將目錄更改為`/manifests`並執行以下命令:👇🏻 ``` kubectl apply -f microservice1-deployment-service.yaml kubectl apply -f microservice2-deployment-service.yaml ``` 執行以下命令檢查我們的兩個部署是否正在**執行**:👇🏻 ``` kubectl get pods ``` ![Kubernetes Pod](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywsvodcqqbx1wv0kede1.png) 最後,我們的應用程式已準備就緒,並使用必要的部署配置部署在 Kubernetes 上。 🎉 *** ## **安裝 Odigos 😍** > 💡 [**Odigos**](https://odigos.io/) 是一個開源可觀察性控制平面,使組織能夠建立和維護其可觀察性管道。 ![Odigos - 監控工具](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7c6i7wth5l3ey9frk0cx.jpg) > ℹ️ 如果您在 Mac 上執行,請執行以下命令在本地安裝 Odigos。 ``` brew install keyval-dev/homebrew-odigos-cli/odigos ``` > ℹ️ 如果您使用的是 Linux 計算機,請考慮透過執行以下命令從 GitHub 版本安裝它。確保根據您的 Linux 發行版更改該檔案。 > ℹ️ 如果 Odigos 二進位檔案不可執行,請在執行安裝指令之前執行此指令 `chmod +x odigos` 使其可執行。 ``` curl -LJO https://github.com/keyval-dev/odigos/releases/download/v1.0.9/cli_1.0.9_linux_amd64.tar.gz tar -xvzf cli_1.0.9_linux_amd64.tar.gz ./odigos install ``` ![Odigos 安裝](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/145z2j9fusgnbp41whcw.png) > 如果您需要有關其安裝的更多簡短說明,請按照此[**連結**](https://docs.odigos.io/installation)操作。 現在,Odigos 已準備好執行 🎉。我們可以執行它的 UI,配置追蹤後端,並相應地發送追蹤。 *** ## **將 Odigos 連接到追蹤後端 💫** > 💡 [**Jaeger**](https://github.com/jaegertracing/jaeger) 是一個開源的端對端分散式追蹤系統。 ![Odigos - 分散式追蹤平台](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9bytdpf4wv1ncb0z52p.jpg) ### **設定 Jaeger!** ✨ 在本教程中,我們將使用 **Jaeger** 🕵️‍♂️,這是一個流行的開源平台,用於查看微服務應用程式中的分散式追蹤。我們將用它來查看 Odigos 生成的痕跡。 > 有關 Jaeger 安裝說明,請點選此 [**link**](https://www.jaegertracing.io/download/)。 👀 若要在 Kubernetes 叢集上部署 Jaeger,請執行下列命令:👇🏻 ``` kubectl create ns tracing kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/jaeger.yaml -n tracing ``` 在這裡,我們建立一個「tracing」命名空間,並在該命名空間中為 Jaeger 應用部署配置📃。 此命令設定自託管 Jaeger 實例及其服務。 👀 執行以下命令來取得正在執行的 pod 的狀態:👇🏻 ``` kubectl get pods -A -w ``` 等待所有三個 Pod 都 **正在執行**,然後再繼續。 ![Kubernetes Pod](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n41rxtp8gcbe4cwsl6xx.png) 現在,要在本地查看 Jaeger Interface 💻,我們需要進行連接埠轉送。將流量從本機電腦上的連接埠 16686 轉送至 Kubernetes 叢集中選定 pod 上的連接埠 16686。 ``` kubectl port-forward -n tracing svc/jaeger 16686:16686 ``` 此命令在本機電腦和 Jaeger pod 之間建立一條隧道,公開 Jaeger UI,以便您可以與其互動。 最後,在瀏覽器上開啟「 http://localhost:16686 」並查看 Jaeger 實例正在執行。 ![Jaeger UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr6bcqph7nyxa7v0u01t.png) ### **設定 Odigos 與 Jaeger 一起工作!** 🌟 > ℹ️ 對於 Linux 用戶,請前往從 GitHub 版本下載 Odigos 二進位檔案的資料夾,然後執行以下命令來啟動 Odigos UI。 ``` ./odigos ui ``` > ℹ️ 對於 Mac 用戶,只需執行: ``` odigos ui ``` 造訪“ http://localhost:3000 ”,您將看到 Odigos 介面,您將在“default”命名空間中看到您的部署。 ![Odigos 登陸頁](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14yqd2x41i9gqvwxdtsu.png) 選擇這兩個選項並點擊“下一步”。在下一頁上,選擇 Jaeger 作為後端,並在出現提示時加入以下詳細資訊: - **目的地名稱🛣️**:提供您想要的任何名稱,例如說**快速追蹤**。 - **端點🎯**:為端點加上`jaeger.tracing:4317`。 就是這樣 - Odigos 已準備好向我們的 Jaeger 後端發送痕跡。就是這麼簡單。 🤯 ![具有兩個微服務的 Odigos UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqmo7div92zngnkdwwyu.png) *** ## **查看分散式追蹤 🧐** 設定 Odigos 後,在 Jaeger 主頁「 http://localhost:16686 」上,您將已經看到列出的兩個微服務。 ![Jaeger UI 列出了兩個微服務](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwb0qjdmxi4ydcvwjgr1.png) Odigos 已經開始向 Jaeger 發送我們的應用程式痕跡。 😉 請記住,這是我們的微服務應用程式。由於以「microservice1」為起點,因此再向「microservice1」發出一些請求,隨後它將向「microservice2」請求資料並傳回。最終,Jaeger 將開始填滿這些痕跡。 ![Jaeger 分散式追蹤](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u4kwzh854bsh5wga1or3.png) 點擊任一請求,您應該能夠觀察請求如何流經您的應用程式以及完成每個請求所需的時間。 這一切都是在沒有更改一行程式碼的情況下完成的。 🤯 一切都感謝 **Odigos**! 🤩 ![令人震驚的 GIF](https://media.giphy.com/media/l0NwHXQy3kUSfFF60/giphy.gif) 想像一下,這只是一個很小的虛擬應用程式,但對於一個執行著大量微服務並相互交互的更大的應用程式來說,分散式追蹤將非常強大! 💪 透過分散式跟踪,您可以輕鬆辨識應用程式中的瓶頸,並確定哪個服務導致問題或花費更長的時間。 🕒 *** ## **讓我們總結一下! 🥱** 到目前為止,您已經學習如何使用 **Odigos** 作為應用程式和追蹤後端 **Jaeger** 之間的 **中間件**,透過分散式追蹤來密切監控 👀 Javascript 應用程式。 👏 如果您已經做到了這一步,請拍拍自己的背。 🥳你值得擁有! 😉 本教學的源程式碼可在此處取得: https://github.com/keyval-dev/blog/tree/main/odigos-monitor-JS-like-a-pro > 如果您對本文有任何疑問或建議,請在下面的評論部分分享。 👇🏻 那麼,這就是本文的內容。感謝您的閱讀! 🎉🫡 --- 原文出處:https://dev.to/odigos/monitor-your-javascript-application-like-a-pro-581p

初級開發人員需要掌握的 12 個資深開發人員特質 🔥

在任何領域,無論是藝術、體育還是軟體開發,達到頂峰的最快方法就是研究那些已經處於頂峰的人……並做他們正在做而你沒有做的事情。 如果您以編寫程式碼為生,這意味著要考慮一下高級開發人員。這意味著確定他們擁有哪些你不具備的技能、習慣和特質。 在過去 3 年裡與全球頂尖軟體工程師一起工作了數千個小時之後,我發現您現在就可以實施 12 種高級開發人員特質,以快速將您的成長提升到一個新的水平。 讓我們從第一開始… ## 1. 專注 專注意味著對某些事情說不,這樣我們就可以做其他事情。 理想情況下,對不重要的事情說不。並對那些能帶來改變的事情說「是」。使船移動得更快的東西。 這對許多開發人員來說確實很難,因為它違背了我們的本能。這意味著接受你無法完成所有事情。並不是每個機會都是平等的。 你不可能學習所有新的框架。您無法閱讀所有時事通訊。您不可能參加所有會議。而你不必這樣做。 你的時間有限。你的能量也是如此。 成為高級開發人員意味著選擇你的戰鬥。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wftnt9w68gjflh2yghs0.png) > 「人們認為專注意味著對你必須關注的事情說『是』。但這根本不是這個意思。這意味著對其他一百個好主意說不。” ——史蒂夫‧賈伯斯 有趣的是,你選擇的越好,你進步的速度就越快。高級開發人員每天都有 24 小時的時間。但他們做得更多。 如何? 透過少做事。 當新事物出現時,問問自己“這真的很重要嗎?”或者這只是另一個趨勢?很可能這只是另一個偽裝成機會的干擾。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgqenoavc69esm48yf06.png) 高級開發人員說的「不」多於「是」。他們完成的專案比開始的專案還要多。他們在學習新框架之前先掌握已經使用的框架。如果你想更快進入高級,你需要培養的第一個特質就是專注。 ## 2. 二階思維 讓「初級開發者」尖叫的一件事是「讓我們建造它,我們會找到結果」的態度。年輕人傾向於先編碼,後思考。 如果您剛開始,這可能是一個很好的態度,但是當您開發可用於生產的軟體時,您將無法更改一些技術決策。或者很容易改變。 例如,您選擇Vue作為前端框架。 然後,需求會改變。你開始認為 React 會是更好的選擇。當然,你可以切換到 React。但這既不容易,也不便宜。 資深開發人員知道,靠自己的供應很容易獲得快感。但是,如果您愛上了您最了解的框架和函式庫,您將開始做出糟糕的技術決策。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9eb6xwgv7jhmn4p7qcq1.png) 他們會三思而後行,考慮自己選擇的後果。這可能意味著在嘗試理解問題時詢問「五個為什麼」。 或考慮他們的解決方案可能存在的缺點。 例如,現在我們新增了 Redux,全域狀態可能更容易管理。但我們必須在 Redux 上招募新的開發人員。學習曲線很高。 而且,你猜怎麼著,我們的 JavaScript 套件會變得更大,這對效能不利。 考慮二階環境將使您成為更好的開發人員。它還將在技術面試中為您提供幫助。 🚨 PS您是否希望快速晉升為擁有優質資源、回饋和責任的高階開發人員? [點擊此處加入我們的免費社區 - 高級開發學院。](https://bit.ly/3GJuOjr) 🚨 ## 3.實用主義 當初級開發人員閱讀一本關於最佳實踐的書時,他們會跳起來並嘗試將它們應用到任何版本中的每一行程式碼。他們虔誠地追隨他們。 如果您無法自己做出技術決策,那麼遵守預先定義的規則會容易得多。但軟體開發不是一種宗教。 一個很好的例子是測試。 當初級開發人員閱讀 TDD(測試驅動開發)時,他們將開始嘗試測試所有內容。旨在實現完整的程式碼覆蓋率。事實上,完整的程式碼覆蓋率會帶來遞減的結果,並且最終會浪費時間。 ![每個發現 TDD 的初級開發人員](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/do0uxbjna2alz58b3mvg.png) 高級開發人員知道如何平衡最佳實踐和上市時間。何時走捷徑,何時不走捷徑。 快速破解會產生錯誤和技術債。當程式碼上下文發生變化時,始終遵守規則會導致錯誤的決策。 你需要一個平衡。 根據情況重新考慮您的技術選擇。 ## 4. 沒有什麼好證明的 由於缺乏自信,初級開發人員發現自己不斷地試圖向他人證明自己。與對自己的價值和技能缺乏安全感的高級開發人員一樣。 他們的信心是建立在他人的認可之上。 這是一場失敗的遊戲。 他們會嘗試在某個技術討論、與他人交談或在深夜或週末推送程式碼時展示自己了解多少。 事實上,所有這些行為都會造成有毒的團隊環境並適得其反。在最好的情況下,他們會讓你看起來比實際情況更高級。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sfp7p24zru1r9zafd05.png) 獵豹不需要在比賽中證明自己,它只是為了狩獵而奔跑。 有兩種方法可以解決這個問題。 第一個是停止在外部驗證上花費太多。因為事實是你不需要向任何人證明自己。只對你自己。 第二是與頭腦中的負面聲音和平相處。 你可以成為你最嚴厲的批評者。完美主義、對失敗的恐懼以及對「真正的」開發人員的錯誤認知正在摧毀你的自尊。這就是為什麼無論你多努力,你總是感覺功虧一簣。 是時候擺脫你的頭腦了。 專注於掌握你的手藝,剩下的就會水到渠成。您將立即對自己和自己的技能更加自信。你將不再試圖向陌生人證明自己。 ## 5. 掌握基礎知識 每當我在 LinkedIn 上看到開發人員的個人資料,並且他們將自己描述為「React」開發人員或「Angular」開發人員時,我就知道他們不是高級開發人員。他們可能是該框架中的高級人員,但總體而言不是高級人員。 框架開發人員永遠不會成為高級開發人員。 框架不會讓你成為高級,因為框架只是錦上添花。不是蛋糕本身。冰山一角與其底部。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chomoxfdvoemx4m4n15o.png) 我甚至推測,目前軟體開發人員中冒充者症候群盛行的背後,甚至是高階開發人員的背後,並不是缺乏天賦,也不是缺乏努力。 這是基本面薄弱。 這也是為什麼除錯或效能優化等主題對於大多數開發人員來說是一個猜謎遊戲。他們不習慣深入挖掘他們正在使用的庫和工具的表面。 要成為高級開發人員,您不僅必須了解事物背後的“什麼”,還必須了解事物背後的“原因”。 例如,高級開發人員不僅能夠建立 React 應用程式。但他們也會理解為什麼 React 是以某種方式建構的。以及它如何與編寫的語言(JavaScript/TypeScript)和執行的平台(Web 瀏覽器)融合。 好訊息是,一旦你掌握了基本原理,一切的水平都會上升。 🚨 PS您是否希望快速晉升為擁有優質資源、回饋和責任的高階開發人員? [點擊此處加入我們的免費社區 - 高級開發學院。](https://bit.ly/3GJuOjr) 🚨 ## 6. 端對端交付 公司避開初級開發人員的第一大原因是他們需要大量外部協助才能完成工作。外部幫助意味著您將打擾高級開發人員來完成您的工作。 初級開發人員被認為“昂貴”,因為他們無法獨立交付。 相反,高級開發人員可以提供端到端的服務。給他們一堆要求,他們會解決剩下的問題。這並不意味著他們是獨狼,而且他們通常非常擅長團隊合作。 這並不意味著高級開發人員快速破解事物只是為了推動它們前進。 那不是「真正的」前輩。 這並不意味著他們深入了解軟體開發生命週期的每個部分。 但是,高級開發人員了解整個軟體開發生命週期的所有主要部分。並且可以為其中的每一個(前端、後端、部署)做出貢獻。 如果您是想要升級的初級/中級開發人員,那麼端對端交付是您需要關注的特徵。 ## 7. 心智模型 高級開發人員與初級開發人員的主要區別之一是他們可以處理的複雜性。 老年人可以理解更複雜的程式碼庫和需求。 他們可以理解二階環境。程式碼庫的變化將如何影響效能、成本甚至團隊。 他們這樣做並不是因為他們記住了每個實作細節。這是不可能的,因為人類的記憶非常有限。 他們這樣做是因為他們將程式碼的複雜度抽象化為心理模型。這些都是表示現實的簡單方法。 開發人員如何建構高品質的心理模型? 透過查看框架和庫的背後並學習它們背後的設計模式。根據您的技術堆棧,存在著許多噪音。諸如 SOLID 原則或 MVC 之類的東西... 但我認為最好的開始方法是選擇您正在使用的任何框架並嘗試超越程式碼。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk2opgm1njc76p0a6k0n.png) 開始問自己,為什麼框架的建立者要這樣建構它?它是建立在新概念的基礎上還是只是古老原則的實現(通常是這種情況)? 透過回答這些問題,您將建立軟體開發的思維模型,並能夠處理更多的複雜性。這是快速成長為高級開發人員的最有效方法之一。 🚨 PS您是否希望快速晉升為擁有優質資源、回饋和責任的高階開發人員? [點擊此處加入我們的免費社區 - 高級開發學院。](https://bit.ly/3GJuOjr) 🚨 ## 8. 資深開發人員控制故事 高階開發人員可以做得非常好的一件事是領導技術討論並影響周圍的其他人。無論是業務利害關係人、產品經理或其他開發人員,資深開發人員都知道如何引導他們朝著正確的方向發展。 他們結合自信、技術專長和溝通技巧來做到這一點。 高級開發人員也能夠設定嚴格的界限。 他們可以不同意而不會情緒激動。他們可以在會議期間為自己(和他人)挺身而出。他們積極協商薪資。 他們講述自己的故事。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pd8vutmtz3wbxas13ey1.png) 高級開發人員知道如何以及何時在沙子上劃線並說“夠了”。 如果另一個開發人員在程式碼審查期間開始指責其他人,老年人知道如何阻止他們。如果高階主管試圖介入開發人員的工作並進行微觀管理,高階管理層知道如何在不破壞關係的情況下阻止他們。 沒有關於如何變得更加自信的開發人員的分步指南。 這需要重複和練習。第一步是停止一直說「是」。並開始嘗試在薪資談判中取得進展。 ## 9. 長期思考 初級開發人員考慮“現在”。他們的想法是短期的。當他們走捷徑時,他們的程式碼也是如此。初級開發人員會擴展一段程式碼,而不考慮正確重構它,或乾脆忽略測試和效能。 但青年人也會對自己的職業生涯進行短期思考。 這可能意味著跳槽過多或自毀前程。這可能意味著忽視。 就像不提高你的技能或推銷自己的方式一樣,因為現在你的工作很穩定。只是被解僱六個月後才後悔。 成為更高級的開發人員的一部分是開始進行長期思考。 第一個方法是改變你的心態。大多數初級開發人員的短期思維不是由懶惰引起的,而是由自我懷疑引起的。 他們內心深處仍在思考成為開發人員是否適合他們。或者他們是否選擇了正確的職業。 這些疑慮阻止他們做出長期承諾。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sw1r4ng1hoyigg3e0z6v.png) 好事需要時間,資深開發人員知道這一點並相應地調整他們的想法。 現在,隨著人工智慧威脅到軟體開發的終結,這種短期思維比以往任何時候都更加頻繁。如果某件事很快就會消失,為什麼還要承諾呢? 相信我,只有當我完全致力於我作為開發人員的職業生涯時,事情才開始起飛。 我說:「就是這樣」。 我不再向外張望。我告訴自己:這是我現在的工作,也是我未來十年的工作,所以讓我把它做好吧。 我開始投資我的技能,因為現在我知道它們會得到回報。 即使你未來 20 年不打算寫程式碼,擁有長遠的心態也會為你帶來巨大的好處。高級開發人員之所以能夠達到高級水平,是因為他們致力於自己的技術。如果您渴望實現這一目標,您也應該這樣做。 🚨 PS您是否希望快速晉升為擁有優質資源、回饋和責任的高階開發人員? [點擊此處加入我們的免費社區 - 高級開發學院。](https://bit.ly/3GJuOjr) 🚨 ## 10.卓越是一種習慣 我想正是 Kent Beck 說過那句名言:「我不是一個偉大的程式設計師,只是一個有著好習慣的好程式設計師」。習慣很重要,因為它們經得起時間的考驗。 因為您擁有的任何關於 JavaScript 框架的知識遲早都會過時。技術變革。但你的習慣將永遠伴隨你。 好訊息是人類是習慣的動物。 在我們的大腦中設定新的慣例並不容易。 但一旦我們將它們內化為習慣,我們就很容易堅持下去。利用這一點的最佳方法是實現您的任何目標並將其分解為日常行動。然後透過重複將這些行為變成習慣。 例如,如果您想更好地進行測試,請每天編寫一個單元測試。 如果您想在日常會議中做好更多準備並清晰思考,請寫日記。如果你想找到一份新的開發人員工作,並且你必須發送 100 份申請,那麼每天發送 10 份申請。 養成新的習慣,你向高級水準的進步將持續且穩定。 ## 11. 保護您最重要的資產 身為高階開發人員意味著不僅要長遠考慮您的程式碼和技術決策,還要考慮您的健康。 因為健康就是財富。 我在影片中一次又一次地談論這一點。 開發人員的工作需要久坐。您一天的大部分時間都坐在電腦前的椅子上。這對你的健康非常不利。 然後,辦公室裡到處都是垃圾食品,像是薯條、汽水和糖果。這意味著除非您有意識地努力,否則您將很難保持健康和體形。 但如果你想擁有一個長期而富有成效的軟體編寫職業,並且不想最終出現背部問題、糖尿病,甚至更糟糕的情況,那麼你需要開始照顧自己的健康。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsdohne0ydvireyloigf.png) 欲得金蛋,勿殺鵝。如果你想提高工作效率,首先要照顧好自己。 這並不意味著您必須開始每週去健身房 5 次。 或進行一些瘋狂的節食。但每周至少2至3次運動。您可以去健身房、跑步或參加團隊運動。現在我正在做 在飲食方面,減少糖和精緻碳水化合物的攝取。肉也不要過量。 也要考慮您的心理健康。 忽略諸如「吃飯、睡覺、編碼、重複」之類的建議,在工作之外建立自己的生活。 開始一個新的嗜好。聯繫朋友。休息一下。 從短期來看,你的進步可能會慢一些。但從長遠來看,你將能夠在遊戲中停留更長時間。 🚨 PS您是否希望快速晉升為擁有優質資源、回饋和責任的高階開發人員? [點擊此處加入我們的免費社區 - 高級開發學院。](https://bit.ly/3GJuOjr) 🚨 ## 12. 閉合圓圈 最後,資深開發人員了解業力是如何運作的。他們知道,無論他們多麼努力,或者多麼聰明,在他們走向頂峰的道路上,都有數十個人的幫助。 這並沒有剝奪他們的優點,但也承認其他人。 所以他們關閉了這個圈子。 他們幫助其他開發人員。他們這樣做是沒有期望的。 不是因為它可能會讓你升職。或是地位,或是仰慕。他們這樣做是因為這是正確的事。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/urp75psyn2lz8oah3cq7.png) 甚至科比·布萊恩也抽出時間來指導年幼的孩子並讓他們進入籃球領域。您也可以抽出時間來幫助新開發人員。 幫助剛起步的人會帶給你部分火花。初學者第一次看到事物時所感受到的熱情和好奇心是如此具有感染力。 另一件你可以變成日常習慣的事情! 好的,就是這樣。具備這 12 個特徵,您將快速成長到高級甚至更高級別。 --- 原文出處:https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m

2024 年您必須嘗試的 25 個 Web 開發專案

毫無疑問,掌握 Web 開發最有效的方法之一就是透過實作。雖然學習理論概念很重要,但將您的知識應用到現實世界的專案中才能真正鞏固您的技能。無論您是想要打下堅實基礎的初學者,還是尋求新挑戰的經驗豐富的開發人員,這裡有 25 個 Web 開發專案可以提高您的能力。 ### 學生成績管理系統 學生成績管理系統旨在為學生和大學提供一種快速且用戶友好的方式來存取和管理考試成績。學生可以登入查看他們的成績,新生可以選擇註冊。該系統旨在以易於理解的方式呈現結果。 **如何做:** 掌握前端、後端和資料庫程式設計的基礎知識後,從建立全端應用程式開始。利用HTML、CSS、JavaScript、PHP和MySQL實現使用者認證、結果顯示和註冊功能。 ![學生成績管理系統](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y9a2bm1exqbu34lsxph.png) ### 線上程式碼編輯器(React) 該專案涉及使用 React 建立線上程式碼編輯器,允許使用者用各種程式語言編寫和執行程式碼。目標是建立一個用戶可以無縫編輯和測試原始程式碼的平台。 **如何做:** 先使用 HTML、CSS 和 React 進行前端工作。實現程式碼輸入、執行和結果顯示功能。專注於建立用戶友好的介面,以獲得流暢的程式碼編輯體驗。 ![線上程式碼編輯器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06jjz3v5sq7c6apc41d7.png) ### 使用 React 進行 Amazon 克隆 Amazon Clone 專案圍繞著使用 React 建立 Amazon 線上商店的工作副本。該專案將幫助您了解有效的電子商務網站所需的元件並將它們應用到您的應用程式中。 **如何做:** 從 HTML、CSS 和 JavaScript 開始。使用 React 建立電子商務網站的不同部分,例如產品清單、購物車和結帳流程。整合動態資料並增強使用者介面。 ![使用 React 的 Amazon 克隆](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pq55ml71nqntt4j07p1z.png) ### 客戶關係經理 客戶關係管理器專案涉及建立一個後端 Web 應用程式,該應用程式允許建立、讀取、更新和刪除 (CRUD) 客戶資料。這是了解後端 Web 開發的基礎專案。 **如何做:** 利用 Node.js、Express.js 和 MongoDB 等技術來建立後端基礎架構。實施 CRUD 操作來管理客戶資料。開發一個用戶友好的介面,用於與客戶資料庫互動。 ![顧客關係經理](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfr25p8b2gzapen1l8ry.png) ### 排序展示台 排序可視化器專案旨在提供各種排序演算法的可視化表示。使用者可以觀察不同的演算法如何執行,並更深入地了解 JavaScript 的基本概念。 **具體操作方法:** 使用 HTML、CSS、Bootstrap 和 JavaScript 建立 Web 應用程式。實現冒泡排序、合併排序和快速排序等排序演算法的視覺化。允許用戶與視覺化進行交互,以增強他們的學習體驗。 ![排序視覺化工具](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51wpf82samc6k9ggftgc.png) ### 多人遊戲 – Connect4 多人遊戲 – Connect4 專案專注於建立具有多人遊戲功能的著名 Connect4 遊戲。它提供了學習一些重要的網路和遊戲設計基礎知識的機會。 **如何做:** 如果您想知道多人遊戲是如何開發的,或者您曾經想為週末製作一款遊戲,那麼這個專案適合您。使用 PyGame、Sockets 和遊戲編程為您和您的朋友建立多人 Connect4 遊戲。 ![多人遊戲 – Connect4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktsz3ky4pj27b9q7mynm.png) ### YouTube 腳本摘要器 投入時間觀看可能比預期更長的電影變得相當具有挑戰性。有時,如果我們不能從他們那裡收集有用的訊息,我們的努力可能會徒勞無功。透過自動總結影片的文字記錄,我們可以輕鬆地發現這些影片中的關鍵主題,這節省了我們再次觀看整個影片的時間和精力。 **如何做到這一點:** 人們每天都會觀看 YouTube 影片,這些影片可以是指導性的、紀錄片的或任何其他持續時間較長的類型;考慮透過提供摘要資訊可以節省多少時間。該專案將是一個 chrome 擴展,它將向後端的 Rest API 發送請求,該 API 將向您發送 YouTube 腳本的摘要。 ![YouTube 腳本摘要](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k4kw614tpyvyrumjc1g8.png) ### OurApp – NodeJS 中的社交媒體 Web 應用程式 現實應用程式 OurApp 的用戶可以進行交流、相互關注以及發布簡短的推文。掌握 HTML、CSS 和 JS 後,專案最適合想要使用 Nodejs 和 MongoDB 深入研究完整堆疊的人。 **怎麼做:** 你想成為能夠超越 HTML、CSS 和 JS 的全端開發人員嗎?建立這個完整的堆疊應用程式,以了解如何使用 NodeJS、MongoDB 和其他技術來建立現代、快速且可擴展的伺服器端 Web 應用程式。如果您想在磨練 NodeJS 技能的同時開發一些有趣的東西,那麼這個專案就是適合您的。您還可以免費註冊全端 Web 開發課程,這將幫助您成為您所在領域的傑出開發人員。 ![OurApp – NodeJS 中的社交媒體 Web 應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02qifmojncuvx27k6hyu.png) ### Codechef 通知 CodeChef 經常遇到伺服器過載問題,導致評審難以快速提供提交結果。留給編碼人員的唯一選擇是在一段時間後不斷檢查站點,看看結果是否存在。透過這個專案,我們希望消除審查提交頁面以確定提交結果的額外步驟。我們將自動執行檢索結果的過程並在準備好後立即通知使用者。 **如何操作:** Codechef 是一個流行的編碼實踐平台,但伺服器過載可能會導致結果延遲。此附加元件旨在透過自動化獲取結果並及時通知用戶的流程來節省時間。使用網路抓取或 API 來收集結果資訊並實作通知系統。 ![Codechef 通知程序](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k7ru3ff3h7tgne8qpoi.png) ### 使用 Dash 來視覺化和預測股票 該專案涉及使用 Dash(一種用於建立分析 Web 應用程式的 Python 框架)來視覺化和預測股票資料。它提供了將資料視覺化和機器學習概念應用於金融資料的機會。 **如何操作:** 如果您對股票市場感興趣,該專案將簡化股票資料的可視化。利用Python、Dash和相關函式庫進行資料視覺化。實施基於歷史資料預測股票趨勢的功能。 ![使用 Dash 視覺化和預測股票](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovs08g50etufj84gz6fd.png) ### 線上程式碼編輯器 (JQuery) 線上程式碼編輯器可透過瀏覽器存取,並位於遠端伺服器上。儘管一些線上程式碼編輯器更像是完整的 IDE,但其他編輯器更像是具有語法突出顯示或程式碼完成等基本功能的文字編輯器。 **如何操作:** 使用 HTML、CSS、JavaScript 和 JQuery 建立線上程式碼編輯器。專注於透過語法突出顯示和程式碼完成等功能來增強使用者體驗。確保程式碼輸入和執行順利。 ![線上程式碼編輯器 (JQuery)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1vxgxvbtf1rh578lauc.png) ### 模糊URL FuzzyURLs 涉及使用 Django(Python 的高級 Web 框架)建立 URL 縮短服務。它提供了建立 Web 應用程式的實務經驗,特別關注 URL 操作。 **如何做:** 從頭開始開發一個基於 Django 的 URL 縮短器。了解 URL 縮短服務的工作流程並實現建立、管理和重新導向短 URL 的功能。 ![FuzzyURLs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5uouta53v2suc8m27i14.png) ### 使用 React 進行 Slack 克隆 該專案旨在使用 React 建立 Slack 克隆,提供即時訊息和協作的平台。這是一個中高階專案,強調React-Redux和Firebase。 **如何做:** 應用 React-Redux 原理來建立一個類似 Slack 的 Web 訊息服務。利用 Firebase 實現即時資料庫功能。專注於建立響應靈敏且功能豐富的訊息傳遞應用程式。 ![使用 React 的 Slack 克隆](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kugsfjeblq934ceomlhs.png) ### Web 應用程式的 Node.js 驗證 了解使用 Node.js 為 Web 應用程式建立驗證系統。探索各種身份驗證技術,評估其優點和缺點,並實施改進。 **如何做:** 對於那些想要深入研究 Node.js 並了解建立安全身份驗證系統的複雜性的人來說,這個專案非常適合。實施使用者身份驗證、會話管理並探索增強安全性的方法。 ![Web 應用程式的 Node.js 驗證](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fcet0kd7abf6xu57eh8.png) ### TinyMCE 同義詞插件 為 TinyMCE 富文本編輯器建立一個插件,用於搜尋單字的同義詞並允許使用者將它們插入編輯器中。 **如何做到這一點:** 為 TinyMCE 開發一個自訂插件,整合一項功能,使用戶能夠搜尋同義詞並輕鬆地將它們插入到富文本編輯器中。了解 TinyMCE API 以實現無縫整合。 ![TinyMCE 同義詞外掛](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nmr8y3x21l9g7vuwz5mi.png) ### 迷宮裡的老鼠 建立一個基本的 React Web 應用程式,顯示老鼠從帶有預設障礙的方形迷宮的左上角到右下角可以採取的所有可能路徑。 **具體操作方法:** 建立一個簡單的 React Web 應用程式來直觀地呈現經典的 Rat in the Maze 謎題。實施功能來展示老鼠穿過迷宮的所有潛在路徑。 ![迷宮中的老鼠](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdcwf4cioua8fogrsp96.png) ### 簡歷產生器 Web 應用程式 使用 ReactJS 和 NodeJS 建立一個用於建立履歷的 Web 應用程式。該專案將指導您完成建立簡歷產生器的步驟,並提供一種實用的方法來支援個人製作簡歷。 **如何做:** 深入研究 ReactJS 和 NodeJS 來開發一個用戶友好的簡歷產生器。實施加入個人詳細資訊、教育背景、工作經驗和技能的功能。專注於建立動態且可自訂的履歷模板。 ![簡歷產生器 Web 應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntwflc67s9kwi00plrti.png) ### Markdown 編輯器 建立一個 Markdown 編輯器,讓使用者編寫 Markdown 並預覽渲染的 HTML。 Markdown 是一種基於網路的文字格式化系統,廣泛用於部落格文章、文件等。 **如何做:** 使用 HTML、CSS 和 JavaScript 開發 Markdown 編輯器。使用戶能夠編寫 Markdown 程式碼並查看渲染的 HTML 的即時預覽。使用粗體文字、圖像和清單等功能增強編輯器。 ![Markdown 編輯器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppv6gl6pzq7uetmkax5b.png) ### 450 DSA 追蹤器 450 DSA Tracker 旨在協助使用者追蹤解決 450 道資料結構和演算法問題的進度。它利用 TypeScript、React.js 的 reducer 和 context API 以及即時瀏覽器 IndexedDB 來快取資訊。 **具體操作方法:** 使用 TypeScript 和 React.js 實作 Web 應用程式,以追蹤解決資料結構和演算法問題的進度。利用reducer 和context API 進行狀態管理,並利用IndexedDB 進行即時瀏覽器快取。 ![450 DSA 追蹤器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijhv2y4gx3f1l2ub7xnz.png) ### 待辦事項網頁應用程式 使用 Node.js 框架 Adonis.js 建立待辦事項 Web 應用程式。了解 HTTP、REST API 和 CRUD 操作,同時建立用於管理待辦事項清單的後端 API。 **如何操作:** 使用 Adonis.js 為待辦事項 Web 應用程式建立 CRUD API。使用 Postman 測試 API 並建立用於新增、更新和刪除任務的後端功能。獲得使用後端框架的經驗。 ![待辦事項 Web 應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3rajw8titifncb6la3e6.png) ### 兩個真相和一個謊言遊戲 Slack 機器人 開發一個 Slack 機器人,用於在 Slack 工作區中玩「兩個真相和一個謊言」遊戲。該專案利用 JavaScript 和 Node.js 為工作區成員建立一個有趣的互動式遊戲。 **如何做:** 建立一個 Slack 機器人,以促進「兩個真相和一個謊言」遊戲。使用 JavaScript 和 Node.js 處理 Slack 工作區中的互動。實現用戶共享陳述並猜測哪一個是錯誤的功能。 ![兩個真相與一個謊言遊戲 Slack 機器人](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwocawujfx0219s6ho5c.png) ### 使用 Chromakey(綠幕)效果進行即時視訊處理 探索視訊處理中使用的色度(綠幕)效果。使用 HTML、CSS 和 JavaScript 建立 Web 應用程式,以背景影片或圖像取代綠幕。 **具體操作方法:** 開發一個處理即時視訊並應用色鍵效果的 Web 應用程式。使用 HTML、CSS 和 JavaScript 操作影片幀並用背景影片或圖像替換綠幕。 ![使用 Chromakey(綠幕)效果進行即時視訊處理](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4yc5aauy13cthc6b2b3.png) ### WhatsApp 網頁克隆 使用 React 和 Firebase 開發具有即時訊息功能的 WhatsApp Web 克隆。 **如何操作:** 使用 React 建立使用者介面並使用 Firebase 實現即時資料庫功能,打造流暢的訊息體驗。 ![WhatsApp 網路克隆](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggf6mpl4bssvzjrr97b3.png) ### WhatsApp 上的電子郵件提醒 設定新電子郵件的 WhatsApp 提醒以簡化電子郵件管理和通知。 **如何操作:** 使用自動化平台 Twilio 建立一個工具,從收件匣中獲取詳細資訊並在 WhatsApp 上發送警報。 ![WhatsApp 上的電子郵件提醒](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zxhacxpysrlx2d78sb5.png) ### 天氣預報應用程式 使用 Streamlit 函式庫和 OpenWeatherMap API 為天氣預報應用程式建立響應式前端。 **如何操作:** 利用 Python 和 Streamlit 可視化天氣資料並與 OpenWeatherMap API 互動以獲取即時天氣資訊。 ![天氣預報應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwm38a5vw8sj2iu17y57.png) ### 總結 這個 Web 開發專案的彙編提供了各種各樣的挑戰,使您能夠提高跨不同技術和概念的技能。無論您對全端開發、資料視覺化、遊戲設計還是自動化感興趣,這些專案都可以提供有價值的幫助 --- 原文出處:https://dev.to/mukeshkuiry/25-web-development-projects-you-must-work-on-2024-4onl

使用 javascript 設定 CSS 樣式

假設你有一個段落。 ``` <p id="target">rainbow 🌈</p> ``` 你需要用JS改變它的顏色。你有什麼選擇? ## 1. 內聯樣式 最直接的路徑。從 DOM 查詢元素並變更其內聯樣式。 ``` document.getElementById('target').style.color = 'tomato'; ``` ![內聯樣式](https://thepracticaldev.s3.amazonaws.com/i/hd67z2je0m8u7zyf7231.jpg) 簡短而簡單。 ## 2. 全域樣式 另一種選擇是建立 `<style>` 標籤,用 CSS 規則填充它並將標籤附加到 DOM。 ``` var style = document.createElement('style'); style.innerHTML = ` #target { color: blueviolet; } `; document.head.appendChild(style); ``` ![全域樣式](https://thepracticaldev.s3.amazonaws.com/i/zhkm5phjflfick5xesu2.jpg) ## 3. CSSOM 插入規則 第三種選擇鮮為人知。我們將使用 [CSSStyleSheet](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet) `insertRule` 方法。 ``` var style = document.createElement('style'); document.head.appendChild(style); style.sheet.insertRule('#target {color: darkseagreen}'); ``` 雖然它可能看起來與第二個選項相似,但它絕對不同。 ![插入規則](https://thepracticaldev.s3.amazonaws.com/i/trjxmsf01o01w8c7u224.jpg) 正如您在 Chrome 開發工具中看到的那樣,“<style>”標籤為空,但樣式(深海綠顏色)已應用於該元素。此外,顏色無法透過開發工具更改,因為 Chrome 不允許[編輯動態 CSS 樣式](https://bugs.chromium.org/p/chromium/issues/detail?id=387952)。 其實這樣的行為才是寫這篇文章的動機。由於性能原因,流行的 CSS-in-JS 庫 [Styled Components](https://www.styled-components.com/) 使用此功能在生產模式下注入樣式。在特定專案或環境中,此功能可能不受歡迎,有些人在專案問題中抱怨它。 ## 4.可建構樣式表(2019 年 7 月更新) 現在可以從 JavaScript 建立 `CSSStyleSheet` 物件。 ``` // Create our shared stylesheet: const sheet = new CSSStyleSheet(); sheet.replaceSync('#target {color: darkseagreen}'); // Apply the stylesheet to a document: document.adoptedStyleSheets = [sheet]; ``` 更多詳細資訊請參閱[此處](https://developers.google.com/web/updates/2019/02/constructable-stylesheets)。 此選項僅對 Chrome 有效,因此請謹慎使用。 您知道使用 javascript 新增樣式的其他選項嗎?這些天你的首選選擇是什麼? 謝謝閱讀! --- 原文出處:https://dev.to/karataev/set-css-styles-with-javascript-3nl5

2024 年掌握前端開發的 9 個專案點子

想要 **在 2024 年掌握前端 Web 開發?** 無論您是渴望開始前端開發之旅還是希望提升您的技能,我們都能滿足您的需求。 這裡有 9 個令人興奮的專案,它們將使您能夠在 2024 年掌握前端開發。為了加速您的學習過程,每個專案都配有專用資源。 讓我們深入研究並將您的編碼願望變成現實! 🚀 ### 1. 說故事作品集網站 建立一個引人入勝的說故事作品集網站來展示您的技能和專案。使用動畫和過渡來吸引訪客。 **您將學到什麼:** 該專案將提高您建立個人作品集、將動畫與 CSS 和 JavaScript 結合的能力。您還將透過網頁設計深入了解如何有效地講述故事。 **技術堆疊:** HTML、CSS、JavaScript、GSAP(GreenSock 動畫平台)。 **資源:** [說故事作品集教學](https://youtu.be/0fYi8SGA20k?si=lgzXlqL7m2aK3nzg) ![說故事組合](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2smmhfqq2g7qx1yune1.png) ### 2. 電影搜尋應用程式 使用 React Hooks 建立電影搜尋應用程式。用戶可以搜尋電影、查看詳細資訊並發現新上映的電影。 **您將學到什麼:** 透過這個專案,您將掌握使用 React Hooks 進行狀態管理、非同步資料擷取和響應式設計。此外,您還將深入了解如何處理使用者輸入和管理複雜的資料結構。 **技術堆疊:** React Hooks、Axios、CSS(flexbox/grid)和電影資料庫(IMDB)API。 **資源:** [電影搜尋應用程式教學](https://www.freecodecamp.org/news/how-to-build-a-movie-search-app-using-react-hooks-24eb72ddfaf7/) ![電影搜尋應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wtwna67o253uusbpoj9.png) ### 3. 任務管理應用程式 開發具有任務建立、完成追蹤和類別組織等功能的任務管理應用程式。 **您將學到什麼:** 該專案將加深您對 React 中的狀態管理、CRUD 操作以及用於任務管理的使用者友好介面的實現的理解。 **技術堆疊:** React、useState、useEffect、localStorage、CSS。 **資源:** [任務管理應用教學](https://youtu.be/m4MDt7UUu1w?si=EcCbIMtkmHZIsWPS) ![任務管理應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/49wmxw4xcfzlig2mrmk4.png) ### 4. 互動式履歷表產生器 建立一個互動式履歷產生器來展示您的職業歷程。包括教育、工作經驗和技能部分。 **您將學到什麼:** 透過這個專案,您將掌握表單處理、動態內容呈現和建立互動式使用者介面的藝術。這是提高你的 React 技能的絕佳機會。 **技術堆疊:** React、表單處理、CSS(樣式元件)。 **資源:** [互動式履歷產生器播放清單](https://youtube.com/playlist?list=PLrL9i_Ka3T0caA37TXSlicITQl1pp_3Ry&si=UhftAkbYr_eYaxJZ) ![互動式履歷產生器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kqsmo0bflp7x9juv94br.png) ### 5.產品落地專案 開發一個產品登陸頁面,重點宣傳特定產品或服務。針對各種螢幕尺寸實施響應式設計。 **您將學到什麼:** 本專案將加深您對響應式網頁設計的理解,包括媒體查詢、Flexbox 和網格佈局。您還將提高建立具有視覺吸引力的登陸頁面的技能。 **技術堆疊:** HTML、CSS(Flexbox/Grid)、響應式設計。 **資源:** [產品登陸頁面教學](https://youtube.com/playlist?list=PL07efmqYWHZ8jroJAkkFB2s4ZKpVNCOQa&si=ZI375j0QMaN7rpdn) ![產品登陸頁](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqpejqx835m7zxgs585u.png) ### 6. 使用 GitHub API 的個人資料頁面 建立一個個人資料頁面,從 GitHub API 取得資料,顯示使用者資訊、儲存庫和貢獻熱圖。 **您將學到什麼:** 該專案將增強您使用 API、處理非同步資料以及建立具有視覺吸引力的使用者設定檔的技能。您還將獲得將第三方 API 整合到應用程式中的經驗。 **技術堆疊:** React、GitHub API、CSS。 **資源:** [GitHub API 設定檔教學](https://dev.to/falanatolu/using-github-api-to-fetch-and-display-a-github-user-profile-26g6) ![使用 GitHub API 的個人資料頁面](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5qvthy4yzgx60a5omp4.png) ### 7.響應式部落格網站 開發一個響應式部落格網站,其中包含針對各種裝置優化的文章清單、單一文章頁面和導航選單等功能。 **您將學到什麼:** 該專案將提高您建立複雜佈局的技能,並專注於回應能力。您將獲得建立導航結構和優化不同螢幕尺寸的使用者體驗的經驗。 **技術堆疊:** HTML、CSS (Flexbox/Grid)、JavaScript。 **資源:** [響應式部落格網站教學](https://youtu.be/NNQuhOeM0mI?si=RjNPOIm-otDhMTsE) ![響應式部落格網站](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/potx6blzf3if4cfp4wv7.png) ### 8. 使用 Lottie 檔案的動畫天氣應用程式 使用 Lottie 檔案建立帶有動畫天氣圖示的天氣應用程式。提供與當前天氣狀況對應的即時天氣資訊和動畫。 **您將學到什麼:** 該專案將擴展您將外部庫 (Lottie) 整合到專案中的技能。您還將獲得使用即時資料 API 和實現動態動畫的經驗。 **技術堆疊:** React、Lottie、OpenWeatherMap API、CSS。 **資源:** [動畫天氣應用教學](https://youtu.be/pFvWwFua6mw?si=Xut6cKy10rV1DpFd) ![動畫天氣應用程式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x392uay0fjf8kypyrtoy.png) ### 9.SaaS 登陸頁面 設計並建置軟體即服務 (SaaS) 產品的登陸頁面。強調簡潔的設計、有效的文案和引人注目的號召性用語元素。 **您將學到什麼:** 該專案將提高您建立以行銷為導向的登陸頁面的技能,並專注於用戶轉換。您還將深入了解有說服力的設計和有效使用配色方案的原則。 **技術堆疊:** React、Tailwind CSS、文案。 **資源:** [SaaS 登陸頁面教學](https://youtube.com/playlist?list=PLz_5rPRIvGEBDvyf-HIIDHjsPppnuXtFG&si=JIpCCIbz4QW8v9o4) ![SaaS 登陸頁](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cl16te1dbqsp5np73bh2.png) 踏上這些令人興奮的專案,在 2024 年掌握前端 Web 開發。每個專案都提供一系列獨特的挑戰和學習機會,讓您具備在動態 Web 開發領域脫穎而出所需的技能。快樂編碼! 🚀 --- 原文出處:https://dev.to/mukeshkuiry/9-projects-to-master-frontend-web-development-in-2024-with-resource-d0k

HTML可以做到這一點嗎?第1部分

歡迎來到我的 HTML can do 這個系列,第 1 部分。 為了與我的[GitHub-Can-Do-This](https://dev.to/yuridevat/reference-a-new-issue-3g5h) 系列保持一致,今天我想寫一篇關於HTML 可以做的很酷的事情的文章(很多人顯然不知道)。 我堅信,越多的人理解 HTML 並充分利用它,網路就會自動變得更容易存取。 ## 表中的內容 1. [詳細資訊和摘要 HTML 標籤](#chapter-1) 2. [電子郵件或電話號碼連結](#chapter-2) 3. [自動完成清單](#chapter-3) 4. [文字修改](#chapter-4) --- 由於我不知道接下來還會有多少部分,因此我將透過按字母順序描述出色的標籤及其背後的 HTML 魔力來開始本系列。 ## 1. 詳細資訊和摘要<a name="chapter-1"></a> 開啟/關閉小部件通常使用 JavaScript 建立。很長一段時間以來,有一個預設的 HTML 標籤恰好涵蓋了這種行為。 樣式可以根據需要進行調整。預設情況下,該小部件是關閉的。賦予 `<details>` 屬性 `open`,它會從頭開始顯示其內容。 {% codepen https://codepen.io/YuriDevAT/pen/dyaBQZm %} ## 2. 連結到電子郵件地址或電話號碼<a name="chapter-2"></a> `<a>` 標籤有一個 `href` 屬性,它指示連結的目的地。它可以連結到網頁、文件、電子郵件地址、同一頁面中的位置或 URL 可以尋址的任何其他內容。 `href` 屬性負責使 `<a>` 可聚焦並在按 Enter 鍵時啟動連結。 ### 連結到電子郵件地址 如果您在「href」的 URL 方案中新增「mailto:」和預期收件者的電子郵件地址,則按一下時會開啟新的外寄電子郵件。 ``` <a href="mailto:[email protected]">Send email to nowhere</a> ``` 您還可以在 URL 中加入更多詳細訊息,包括抄送、密件副本、主題和正文 😯。 ``` <a href="mailto:[email protected][email protected]&subject=This%20is%20the%20subject">Send email with subject to nowhere and nobody</a> ``` 詳細了解[連結至電子郵件地址 rfc6068](https://datatracker.ietf.org/doc/html/rfc6068)。 ### 連結到電話號碼 將電話號碼新增至「tel:」之後的「href」時,您也可以連結到電話號碼。 ``` <a href="tel:+18005551239">(800) 555 1239</a> ``` 連結行為可能因設備而異([關於連結到電話號碼的 MDN 官方文件](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#linking_to_telephone_numbers)): - 在行動裝置上,系統會自動撥打號碼。 - 大多數作業系統都有可以撥打電話的程序,例如 Skype 或 FaceTime。 - 網站可以使用registerProtocolHandler撥打電話,例如web.skype.com。 - 其他行為包括將號碼儲存到聯絡人,或將號碼傳送到另一台裝置。 詳細了解[連結到電話號碼 rfc3966](https://datatracker.ietf.org/doc/html/rfc3966)。 {% codepen https://codepen.io/YuriDevAT/pen/OJdZLKK %} ## 3. 自動完成清單<a name="chapter-3"></a> 使用“<datalist>”,當使用者開始在輸入欄位中寫入時會出現一個下拉式選單,並使他們可以從清單中的可用選項中進行選擇。 {% codepen https://codepen.io/YuriDevAT/pen/zYeVMbE %} ## 4. 文字修改<a name="chapter-4"></a> 使用特定標籤,可以直接修改文本,無需額外的 CSS。非常便利。 {% codepen https://codepen.io/YuriDevAT/pen/LYqKXwJ %} --- 謝謝閱讀。對此,我真的非常感激! --- 原文出處:https://dev.to/yuridevat/html-can-do-this-part-1-3ab2

Flask Rest API -第 1 部分 - 將 MongoDB 與 Flask 結合使用

## 第 1 部分:將 MongoDB 與 Flask 結合使用 你好!在本系列的最後一個[部分](https://dev.to/paurakhsharma/flask-rest-api-part-0-setup-basic-crud-api-4650)中,我們學習瞭如何建立基本的“ CRUD” ` 使用 python `list` 的 REST API 功能。但這不是現實世界應用程式的建構方式,因為如果您的伺服器重新啟動或上帝禁止崩潰,那麼您將丟失伺服器中儲存的所有資訊。為了解決這些問題(以及許多其他問題),使用了資料庫。所以,這就是我們要做的。我們將使用 [MongoDB](https://docs.mongodb.com/manual/) 作為我們的資料庫。 如果您剛從這部分開始,您可以在[此處]找到我們迄今為止編寫的所有程式碼(https://github.com/paurakhsharma/flask-rest-api-blog-series/tree/master/Part% 20 -%200)。 在開始之前,請確保您已在系統中安裝了 MongoDB。如果您還沒有安裝,可以安裝 [Linux](https://docs.mongodb.com/manual/administration/install-on-linux/)、[Windown](https://docs.mongodb.com/手冊/教學/install-mongodb-on-windows/)和[macOS](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/)。 主要有一些流行的函式庫可以讓 MongoDB 的使用變得更容易: 1) [Pymongo](https://api.mongodb.com/python/current/) 是 MongoDB 的低階 Python 包裝器,使用 `Pymongo` 類似於直接編寫 MongoDB 查詢。 以下是使用“Pymongo”更新“id”與給定“id”相符的電影名稱的簡單範例。 ``` db['movies'].update({'_id': id}, {'$set': {'name': 'My new title'}}) ``` `Pymongo` 不使用任何預先定義的模式,因此它可以充分利用 MongoDB 的無模式特性。 2) [MongoEngine](http://docs.mongoengine.org/) 是物件文件映射器,它使用文件模式,使 MongoDB 的使用變得清晰、更容易。 這是使用“mongoengine”的相同範例。 ``` Movies.objects(id=id).update(name='My new title') ``` 「Mongoengine」對資料庫中的欄位使用預先定義架構,這限制了它使用 MongoDB 的無架構性質。 正如我們所看到的,雙方都有各自的優點和缺點。因此,請選擇最適合您的專案的一種。在本系列中,我們將學習“Mongoengine”,如果您希望我也介紹“Pymongo”,請在下面的評論部分告訴我。 為了在我們的`Flask` 應用程式中更好地使用`Mongoengine`,有一個很棒的`Flask` 擴展,名為[Flask-Mongengine](http://docs.mongoengine.org/projects/flask- mongoengine/en/latest/)。 那麼,讓我們開始安裝「flask-mongoengine」。 ``` pipenv install flask-mongoengine ``` *注意:由於`flask-mongoengine` 是在`mongoengine` 之上建造的,所以在安裝Flask-mongoengine 時會自動安裝,而且`mongoengine` 是在`pymongo` 之上建造的,所以它也會被安裝* 現在,讓我們在「movie-bag」中建立一個新資料夾。我將其稱為“資料庫”。在「database」資料夾中建立一個名為「db.py」的檔案。另外,建立另一個檔案並將其命名為“models.py” 讓我們看看文件/資料夾現在是什麼樣子。 ``` movie-bag │ app.py | Pipfile | Pipfile.lock └───database │ db.py └───models.py ``` 現在,讓我們深入探討有趣的部分。 首先,讓我們透過將以下程式碼新增至「db.py」來初始化我們的資料庫 ``` #~movie-bag/database/db.py from flask_mongoengine import MongoEngine db = MongoEngine() def initialize_db(app): db.init_app(app) ``` 在這裡,我們導入了“MongoEngine”並建立了“db”物件,並定義了一個函數“initialize_db()”,我們將從“app.py”中呼叫該函數來初始化資料庫。 讓我們在“models”目錄中的“movie.py”中編寫以下程式碼 ``` #~movie-bag/database/models.py from .db import db class Movie(db.Document): name = db.StringField(required=True, unique=True) casts = db.ListField(db.StringField(), required=True) genres = db.ListField(db.StringField(), required=True) ``` 我們剛剛建立的是資料庫的文件。因此,使用者無法新增此處定義的其他欄位。 這裡我們可以看到「Movie」文件有三個欄位: 1)`name`:是一個`String`類型的字段,我們在這個字段上也有兩個約束。 - “必需”,這意味著用戶在不提供標題的情況下無法建立新電影。 - “唯一”,這意味著電影名稱必須是唯一的,不能重複。 2) `casts`:是一個`list`類型的字段,其中包含`String`類型的值 3) `genres`: 與`casts`相同 最後,我們可以在「app.py」中初始化資料庫,並更改「view」函數(處理 API 請求的函數)以使用我們先前定義的「Movie」文件。 ``` #~movie-bag/app.py -from flask import Flask, jsonify, request +from flask import Flask, request, Response +from database.db import initialize_db +from database.models import Movie app = Flask(__name__) -movies = [ - { - "name": "The Shawshank Redemption", - "casts": ["Tim Robbins", "Morgan Freeman", "Bob Gunton", "William Sadler"], - "genres": ["Drama"] - }, - { - "name": "The Godfather ", - "casts": ["Marlon Brando", "Al Pacino", "James Caan", "Diane Keaton"], - "genres": ["Crime", "Drama"] - } -] +app.config['MONGODB_SETTINGS'] = { + 'host': 'mongodb://localhost/movie-bag' +} + +initialize_db(app) [email protected]('/movies') -def hello(): - return jsonify(movies) [email protected]('/movies') +def get_movies(): + movies = Movie.objects().to_json() + return Response(movies, mimetype="application/json", status=200) [email protected]('/movies', methods=['POST']) -def add_movie(): - movie = request.get_json() - movies.append(movie) - return {'id': len(movies)}, 200 [email protected]('/movies', methods=['POST']) + body = request.get_json() + movie = Movie(**body).save() + id = movie.id + return {'id': str(id)}, 200 [email protected]('/movies/<int:index>', methods=['PUT']) -def update_movie(index): - movie = request.get_json() - movies[index] = movie - return jsonify(movies[index]), 200 [email protected]('/movies/<id>', methods=['PUT']) +def update_movie(id): + body = request.get_json() + Movie.objects.get(id=id).update(**body) + return '', 200 [email protected]('/movies/<int:index>', methods=['DELETE']) -def delete_movie(index): - movies.pop(index) - return 'None', 200 [email protected]('/movies/<id>', methods=['DELETE']) +def delete_movie(id): + Movie.objects.get(id=id).delete() + return '', 200 app.run() ``` 哇!變化很多,讓我們一步一步地進行變化。 ``` -from flask import Flask, jsonify, request +from flask import Flask, request, Response +from database.db import initialize_db +from database.models.movie import Movie ``` 這裡我們刪除了“jsonify”,因為我們不再需要,並加入了“Response”,我們用它來設定回應的類型。然後我們從之前定義的「db.py」導入「initialize_db」來初始化資料庫。最後,我們從“movie.py”導入“Movie”文件 ``` +app.config['MONGODB_SETTINGS'] = { + 'host': 'mongodb://localhost/movie-bag' +} + +db = initialize_db(app) ``` 這裡我們設定 mongodb 資料庫的配置。這裡主機的格式為「<host-url>/<database-name>」。由於我們已經在本地安裝了 mongodb,因此我們可以從“mongodb://localhost/”存取它,並且我們將資料庫命名為“movie-bag”。 最後,我們初始化資料庫。 ``` [email protected]('/movies') +def get_movies(): + movies = Movie.objects().to_json() + return Response(movies, mimetype="application/json", status=200) + ``` 在這裡,我們使用“Movies.objects()”從“Movie”文件中獲取所有物件,並使用“to_json()”將它們轉換為“JSON”。最後,我們傳回一個「Response」物件,其中我們將回應類型定義為「application/json」。 ``` [email protected]('/movies', methods=['POST']) + body = request.get_json() + movie = Movie(**body).save() + id = movie.id + return {'id': str(id)}, 200 ``` 在「POST」請求中,我們首先取得發送的「JSON」和一個請求。然後我們使用“Movie(**body)”請求中的欄位來載入“Movie”文件。這裡的「**」稱為擴充運算符,在 JavaScript 中寫為「...」(如果您熟悉的話)。顧名思義,它的作用是傳播「dict」物件。 <br/> 所以,`Movie(**body)` 變成了 ``` Movie(name="Name of the movie", casts=["a caste"], genres=["a genre"]) ``` 最後,我們保存文件並獲取其“id”,我們將其作為回應返回。 ``` [email protected]('/movies/<id>', methods=['PUT']) +def update_movie(id): + body = request.get_json() + Movie.objects.get(id=id).update(**body) + return '', 200 ``` 這裡我們先找到與請求中發送的「id」相符的Movie文件,然後更新它。這裡我們也應用了擴充運算子將值傳遞給「update()」函數。 ``` [email protected]('/movies/<id>', methods=['DELETE']) +def delete_movie(id): + Movie.objects.get(id=id).delete() + return '', 200 ``` 與此處的“update_movie()”類似,我們獲取與給定“id”匹配的電影文件並將其從資料庫中刪除。 哦,**我剛剛想起來**,我們還沒有將 API 端點加入到“GET”,僅從我們的伺服器獲取一個文件。 讓我們加入它: 在 `app.run()` 上方加入以下程式碼 ``` @app.route('/movies/<id>') def get_movie(id): movies = Movie.objects.get(id=id).to_json() return Response(movies, mimetype="application/json", status=200) ``` 現在您可以從 API 端點「/movies/<valid_id>」取得單一影片。 要執行伺服器,請確保您位於“movie-bag”目錄。 然後執行 ``` pipenv shell python app.py ``` 在終端機中啟動虛擬環境並啟動伺服器。 哇!恭喜您已經走到這一步了。要測試API,請使用我們在[上一篇]((https://dev.to/paurakhsharma/flask-rest-api-part-0-setup-basic-crud-api-4650)) 中使用的“ Postman」本系列的一部分。 您可能已經注意到,如果我們向端點發送無效資料,例如:沒有名稱或其他字段,我們會收到“HTML”形式的不友善錯誤。如果我們嘗試取得資料庫中不存在的「id」影片文件,那麼我們也會收到「HTML」回應形式的不友善錯誤。這並不是一個精心建構的 API 的例外行為。我們將在本系列的後面部分中了解如何處理此類錯誤。 ### 我們從本系列的這一部分學到了什麼? - `Pymongo` 和 `Mongoengine` 之間的差異。 - 如何使用「Mongoengine」建立文件架構。 - 如何使用「Mongoengine」執行「CRUD」操作。 - Python 擴充運算子。 您可以在[此處]找到這部分的完整程式碼(https://github.com/paurakhsharma/flask-rest-api-blog-series/tree/master/Part%20-%201) 在下一部分中,我們將學習如何使用「Blueprint」來更好地建立 Flask 應用程式。以及如何使用“flask-restful”以最少的設定遵循最佳實踐,更快地建立 REST API 直到那時快樂編碼😊 --- 原文出處:https://dev.to/paurakhsharma/flask-rest-api-part-1-using-mongodb-with-flask-3g7d

🔥 NextJS 專案的 12 個頂級庫 🏆

![保存](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szi0gw4l049yctxjeu1p.png) 在過去的十年裡,我一直是一名全端開發人員,建置了像[gitup](https://gitup.dev/) 這樣的較小專案和像[crosspublic](https://github.com/github-20k/) 這樣的更大專案跨公共)。 多年來,我測試了不同的工具: 1. 提高工作效率 2. bug 更少 3. 少寫程式碼 我整理了一系列庫來幫助您開發我每天使用的優秀 NextJS 東西,並解釋了您可以用它們做什麼。 **讓我們深入了解一下。** ![變得更好](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ap38q1ej3tqypjuebg3u.gif) --- # 1. [Trigger.dev](https://github.com/triggerdotdev/trigger.dev) 使用 NextJS,我總是需要幫助來處理與後台作業相關的所有事情。 它可以是在背景執行的 cron 作業,用於傳送電子郵件或處理系統中的新使用者管道。 這導致我執行另一台伺服器來處理這些作業,無論是外部 EC2 伺服器還是帶有事件橋的無伺服器功能。 這會導致我支付額外的服務費用(管理更多服務)並自行管理水平擴展(在某些時候)。 [Trigger.dev](http://Trigger.dev) 改變了這一點,在 NextJS(以及許多其他)之上提供後台作業。 他們也知道如何解決 NextJS 無伺服器逾時限制來處理長時間執行的作業。   ![TriggerDev](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/triggertop.gif) --- ## 2. [Prisma](https://www.prisma.io) Prisma 不是 NextJS 特有的。它是一個與資料庫一起使用的 ORM。 ORM 是資料庫查詢的統一包裝器。 它保持良好的結構,並允許您在不同的資料庫提供者之間快速更改。 雖然您可以使用很多 ORM,但 Prisma 的獨特之處在於為您的查詢提供 Typescript 支持,使一切速度提高 100 倍。 NextJS 在預設配置中使用了 typescript,使其成為完美的匹配。   ![prisma.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/prisma.gif) --- ## 3. [NextAuth.js](https://next-auth.js.org) 假設您要實現任何服務提供者身份驗證,例如 Facebook / Google / GitHub (oAuth)。 在這種情況下,您必須為每個提供者建立實作或使用外部服務,例如 [Auth0](https://auth0.com/) 或 [Clerk](https://clerk.com/)。 如果您打算自行執行此操作,NextAuth 提供了豐富的實現,以便您只需提供正確的金鑰即可輕鬆新增它們。 一旦您登錄,他們也會處理授權。 *Next.JS auth 可以與 Prisma 開箱即用。*   ![authjs.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/authjs.gif) --- ## 4. [下一個網站地圖](https://github.com/iamvishnusankar/next-sitemap) 在伺服器上部署 NextJS 後,您需要協助 google 索引所有頁面。 如果您可以告訴 Google 您網站上的所有頁面,那就更好了。 為此,您可以建立一個列出所有頁面的 sitemap.xml 檔案。 您可以輕鬆地使用 Next-Sitemap 來實現這一點。   ![sitemap.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/sitemap.gif) --- ## 5. [下一步 SEO](https://github.com/garmeeh/next-seo) SEO 是透過向您的網站預覽提供關鍵字、描述和圖像,使您的網站出現在 Google Feed 上以進行不同查詢的過程。 如果您使用新的 NextJS 應用程式路由器,則可能不需要使用它。 您可以使用他們的“導出元資料”方法或“生成元資料”, 但如果您使用舊的應用程式路由器,這是為您的網站加入 SEO 的最佳方式。   ![seo.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/seo.gif) --- ## 6. [Zod](https://github.com/colinhacks/zod) Zod 是一個物件驗證器(伺服器和客戶端)。 您可以在物件上放置不同的規則並稍後對其進行驗證,例如使用者名稱和密碼,或更複雜的內容(例如陣列長度或其他鍵上的條件)。 *Zod 不是 NextJS 特定的。* 多年來,我看過很多物件驗證器,例如 [Yup](https://github.com/jquense/yup) 和 [class-validator](https://github.com/typestack/class-validator)。 是的,它看起來不像 Zod 那樣維護,並且在使用 NestJS 之類的東西時,類驗證器非常強大 - 所以你最好使用 Zod。   ![zod.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/zod.gif) --- ## 7. [React-hook-form](https://github.com/react-hook-form/react-hook-form) 雖然 Zod 可以驗證物件,但如果沒有自訂邏輯,它不會影響您的用戶端和後端。 React-hook-form 是優秀的用戶端驗證專案(顯示輸入錯誤、管理輸入狀態和提交)。 當然,您可以使用 Zod 作為 React-hook-form 的驗證器。   ![hookform.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/hookform.gif) --- ## 8. [tRPC](https://github.com/trpc/trpc) 我承認我以前從未使用過 tRPC,但今天它似乎吸引了許多人的目光。 它與 Prisma 有類似的概念;它們為您的請求和回應產生一個接口,因此當您使用前端呼叫時,您會獲得自動完成功能。 這很好,因為它減少了錯誤的機會 - 假設您修改了後端路由,您將無法編譯專案 - 客戶端將返回不存在的參數或回應鍵的錯誤。   ![trpc.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/trpc.gif) --- ## 9. [SWR](https://swr.vercel.app) 和 [React-Query](https://github.com/TanStack/query) 多年來我一直使用 Axios 和 fetch 作為發送請求的基礎庫。 SWR 和 React-Query 增強了這些函式庫並提供鉤子、快取、轉換等。 強烈推薦用於每個專案。請注意,這些庫適用於客戶端元件(“使用客戶端”),而不是伺服器元件。   ![query.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/query.gif) --- ## 10. [lodash](https://lodash.com) 這不是 NextJS 特定的函式庫。 它是一個用於改變資料的函式庫,雖然這些年來 JavaScript 憑藉像 flatMap 這樣優秀的原生函數取得了很大的進步,但仍然缺少一些東西,例如按鍵或分塊和陣列的唯一陣列。 我發現自己幾乎在所有專案中都使用 lodash。   ![lodash.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/lodash.gif) --- ## 11. [dayjs](https://day.js.org/) day.js 是一個包含與日期、格式、時區等相關的所有內容的函式庫。 我可能會因為那件事而被烤。我多年來一直在使用“moment.js”。 現在它不再維護了,dayjs 是一個不錯的選擇。 有些人喜歡新的 JS 函數來處理日期,但我仍然覺得 dayjs 選項和原生 JS 日期函數之間存在很大的差距。   ![scrolldown.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/scrolldown.gif) --- ## 12. [jsdom](https://github.com/jsdom/jsdom) 這不是必須的,但我最近在許多專案中都使用它作為 [cheerio](https://github.com/cheeriojs/cheerio) 的替代品。 您可以取得整個頁面內容(`<html><body>....</html>)` 並將其轉換為稍後可以使用「本機」javascript dom 函數`querySelector`、`innerHTML` 等來操作的物件… 非常適合需要一些刮擦的專案。   ![jsdomer.gif](https://nevdav2.dreamhosters.com/wp-content/uploads/2023/12/jsdomer.gif) --- 我們在 X 上連接嗎? :) [我在這裡](https://twitter.com/nevodavid) 您是否為 NextJS 使用其他一些很酷的程式庫? 請在評論中讓我了解它們:) --- 原文出處:https://dev.to/nevodavid/top-12-libraries-for-your-nextjs-project-1oob

🔥開發者的 5 個殺手級網站😎

開發者們大家好👋 今天,我將與您分享 5 個令人驚嘆的網站,它們對您的專案開發有幫助,也可以節省您的寶貴時間⏱。 ## 1️⃣ Flaticon Flaticon 是最大的圖示資料庫。您可以在這裡找到各種圖示、介面圖示、動畫圖示和貼紙,並可以以多種格式免費下載,例如 PNG、SVG、EPS、PSD 和 CSS。您也可以使用 Adobe After Effect 編輯現有圖示。 ![Flaticon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nu8u01iceaj2vaxth3dq.png) _造訪此處的網站:[https://www.flaticon.com](https://www.flaticon.com)_ ## 2️⃣ Omatsuri Omatsuri 是一個開源 Web 應用程式,為開發人員提供 12 種不同的工具。它就像“多合一”應用程式。 - **三角形產生器:** 此工具用於為元素和偽元素產生 css 三角形樣式。 - **色調產生器:** 此工具用於產生給定顏色的色調和不同色調。 - **漸層產生器:** 此工具用於產生線性和徑向 css 漸層。 - **頁面分隔線:** 此工具用於使用 css 和 svg 影像產生頁面分隔線。 - **SVG 壓縮器:** 此工具用於使用 SVGO 壓縮 SVG 影像並轉換為 React 元件。 - **SVG -> JSX Converter:** 此工具用於將 SVG 圖示和插圖轉換為 React 元件或其他支援 JSX 的函式庫的元件。 - **base64 編碼器:** 此工具用於將圖像或檔案轉換為 Base64 並產生用作背景圖像的樣式。 - **虛假資料產生器:** 以 JSON Schema 格式產生各種真實的虛假資料,如地址、頭像、姓名、電話等。 - **符號集合:** 此工具包含常用 html 符號的集合:箭頭、標記、貨幣符號等。 - **Lorem ipsum:** 此工具產生不同類型的 lorem ipsum 文字。 - **CSS 遊標:** 這也是所有現有 CSS 遊標屬性值的集合。 - **鍵盤事件程式碼:** 此工具提供 JavaScript 事件鍵盤程式碼值。 ![Omatsuri](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpb3m3i8epgu49ltgwbp.png) _造訪此處的網站:[https://omatsuri.app](https://omatsuri.app/) Github 連結:[https://github.com/rtivital/omatsuri](https://github.com/rtivital/omatsuri)_ ## 3️⃣ RapidAPI RapidAPI 是最大的 API 中心。它提供了大量涵蓋天氣、社交媒體、電子商務、金融等各個類別的 API。您可以輕鬆搜尋 API 並將其整合到您的應用程式中。這裡並非所有 API 金鑰都是免費的,該網站提供免費和付費訂閱。 對於某些 api 金鑰,您需要付費才能使用它們並將其整合到您的應用程式中。 ![快速 API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5o23n6vs7v4xhd8lmt74.png) _造訪此處的網站:[https://rapidapi.com/hub](https://rapidapi.com/hub)_ ## 4️⃣ Storyset Storyset 平台為您提供精彩的免費客製化插圖,供您在專案中使用。使用 Storyset,您可以輕鬆自訂、製作動畫和下載插圖,以建立精美的應用程式,尤其是登陸頁面。它還提供了編輯插圖以及以 PNG 和 SVG 格式下載的選項。 ![故事集](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gzkwislxpeh1dy8ru0r.png) _造訪此處的網站:[https://storyset.com](https://storyset.com)_ ## 5️⃣ Transform Transform.tools 是一個開源網站,讓您能夠轉換各種元素,例如 HTML 到 JSX、JavaScript 到 JSON、CSS 到 JS 物件等等。每當您需要快速轉換或轉換任何內容時,它都將真正節省時間。 ![轉換](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gyc4vvr7luvc93l4a6hd.png) _造訪網站:[https://transform.tools](https://transform.tools) Github連結:[https://github.com/ritz078/transform](https://github.com/ritz078/transform)_ ⬇ 如果您使用過這些工具,請在下面發表評論並分享您的經驗。另外,提及您最常使用的工具。我會將它們包含在下一篇文章中。 感謝您的閱讀❤ --- 原文出處:https://dev.to/dev_kiran/top-5-killer-websites-for-developers-2knm

使用 Jest 和 Supertest 測試 NodeJs/Express API

這是[使用 Express、Sequelize 和 Postgres 建立 API](https://www.oriechinedu.com/posts/performing-crud-with-sequelize/) 的第三部分。在[第二部分](https://www.oriechinedu.com/posts/performing-crud-with-sequelize/)中,我們建立了簡單的API端點來示範Sequelize中的CRUD操作。在本文中,我們將重點放在為第二部分中建立的 API 端點編寫端到端測試。 ### 術語解釋 - **端對端測試** - 一種測試類型,用於測試應用程式從開始到結束的流程是否如預期運作。這也稱為功能測試。此類測試的一個範例是測試端點或路由,其中涉及測試端點工作所需的所有內容,例如資料庫連接、依賴項等。 - **測試執行器** - 在給定目錄或檔案中取得原始程式碼(測試)、執行測試並將結果寫入控制台或任何指定位置的程式庫或工具,例如 Jest、Mocha。 - **Jest** - [Jest](https://jestjs.io/) 是 Facebook 開發的 JavaScript 測試框架。它以最少的配置開箱即用,並具有內建的測試執行器、斷言庫和模擬支援。 - [**Supertest**](https://www.npmjs.com/package/supertest) - 用於測試 Node.js HTTP 伺服器的函式庫。它使我們能夠以程式設計方式向 HTTP 伺服器發送 HTTP 請求(例如 GET、POST、PATCH、PUT、DELETE)並獲取結果。 現在我們已經解釋了基本術語,讓我們深入了解主要業務。 如果您一直按照先前的[文章](https://www.oriechinedu.com/posts/performing-crud-with-sequelize/)進行操作,那麼請在您最喜歡的文字編輯器中開啟它,否則克隆使用的儲存庫[此處](https://github.com/oriechinedu/sequelize-with-postgres-tutorial)。 **第 1 步 - 安裝 Jest 和 supertest** 打開終端機並“cd”到專案根目錄並執行以下命令: ``` npm install --save-dev jest supertest ``` **步驟 2 - 設定 Jest** 打開“package.json”並將以下程式碼新增至其中。 ``` "jest": { "testEnvironment": "node", "coveragePathIgnorePatterns": [ "/node_modules/" ] }, ``` 這是我們測試 API 時需要設定 jest 的基本配置。您希望 `jest` 忽略的任何檔案都放置在 `"coveragePathIgnorePatterns"` 內。 `"coveragePathIgnorePatterns"` 指定一個與要排除的目錄相符的正規表示式,在我們的例子中,我們希望它忽略 `node_modules` 目錄。 接下來我們新增“test”腳本。在 `package.json` 的 `scripts` 部分中,加入以下腳本: ``` "test": "jest" ``` **步驟 3 - 測試配置** 現在,讓我們確認「jest」已準備好執行我們的測試。在終端機中執行“npm test”。您會注意到控制台上列印如下所示的錯誤,這表示「jest」已設定。 ![未指定測試時出現 Jest 錯誤](https://thepracticaldev.s3.amazonaws.com/i/sftb9nkpi1jk076d09xy.png '未指定測試時出現 Jest 錯誤') 讓我們新增一個簡單的測試來驗證配置。建立一個名為「tests」的新目錄並新增一個新檔案「sample.test.js」。在「sample.test.js」中,加入以下程式碼: ``` describe('Sample Test', () => { it('should test that true === true', () => { expect(true).toBe(true) }) }) ``` 現在,執行“npm test”,您將得到如下所示的輸出: ![範例測試輸出](https://thepracticaldev.s3.amazonaws.com/i/4zmad3nkc8stnfyescvi.png) ##### Jest 如何辨識測試檔? Jest 以三種方式辨識測試文件: - 副檔名為「.test.js」的文件 - 副檔名為「.spec.js」的文件 - `__tests__` 資料夾或目錄中的所有檔案。 ## 測試 API 端點 現在我們已經設定了測試環境,是時候開始測試 API 端點了。由於我們的端點需要向資料庫發出請求,因此我們需要設定一個測試資料庫。設定測試資料庫的原因是每次執行測試時我們都會刪除該資料庫。每次執行測試時刪除資料庫可確保測試的完整性。也就是說,如果一個測試是在資料庫中建立一個「post」記錄,我們要確保在測試執行之前資料庫中沒有「post」記錄,這樣,我們就可以確定得到的結果從測試中。 **第 4 步 - 建立測試資料庫** 在本文的[第一部分](https://www.oriechinedu.com/posts/getting-started-with-sequelize-and-postgres/)中,我們建立了兩個資料庫,一個用於開發,另一個用於測試。如果您尚未建立測試資料庫,請依照[連結](https://www.oriechinedu.com/posts/getting-started-with-sequelize-and-postgres/)建立測試資料庫。 **步驟 5 - 設定測試腳本** 我們需要以下腳本: - `pretest` - `pretest` 是一個 npm 腳本,當呼叫 `npm test` 指令時會自動呼叫。我們將掛接命令來更改環境以進行測試,並在每次測試執行之前刷新資料庫。 - `migrate:reset`:此命令將負責在每次測試執行之前刷新資料庫。 現在編輯“package.json”的“scripts”,如下所示: ``` "scripts": { "start-dev": "nodemon index.js", "migrate": "npx sequelize-cli db:migrate", "migrate:reset": "npx sequelize-cli db:migrate:undo:all && npm run migrate", "test": "cross-env NODE_ENV=test jest --testTimeout=10000", "pretest": "cross-env NODE_ENV=test npm run migrate:reset" } ``` 腳本修改需要注意的地方: - [`cross-env`](https://www.npmjs.com/package/cross-env) - 用於設定環境變數的與作業系統無關的套件。我們用它將`NODE_ENV`設為`test`,以便我們的測試可以使用測試資料庫。執行以下命令來安裝跨環境。 ``` npm i -D cross-env ``` - `--testTimeout` 標誌 - 這會增加 Jest 的預設逾時時間,即 5000 毫秒。這很重要,因為測試執行者需要在執行測試之前刷新資料庫。 **第 6 步 - 測試腳本** ``` npm test ``` 如果一切正常,您應該在終端機上看到以下輸出: ![替代文本](https://thepracticaldev.s3.amazonaws.com/i/2panajlcgx7dg0d2oe88.png) 仔細觀察上面的螢幕截圖,您會注意到一行 _`using environment "test"`_ 表示 `cross-env` 已更改了 `NODE_ENV`。 **最後一步 - 測試路由/端點** 現在,讓我們開始為端點編寫測試。在測試目錄中建立一個名為routes.test.js的文件 ``` touch tests/routes.test.js ``` - **測試建立後端點** 將以下程式碼複製到“tests/routes.test.js”中: ``` const request = require('supertest') const app = require('../server') describe('Post Endpoints', () => { it('should create a new post', async () => { const res = await request(app) .post('/api/posts') .send({ userId: 1, title: 'test is cool', }) expect(res.statusCode).toEqual(201) expect(res.body).toHaveProperty('post') }) }) ``` - `describe` 函數用於將相關測試分組在一起 - `it` 是執行實際測試的 `test` 函數的別名。 -“expect”函數使用一組“matcher”函數測試值。 請造訪 [Jest 文件](https://jestjs.io/docs/en/api.html) 以取得 jest 函數的完整清單和詳細資訊。 現在,執行測試 ``` npm test ``` 輸出如下圖所示: ![替代文本](https://thepracticaldev.s3.amazonaws.com/i/yt6o537gzw29030siy6c.png) 有關所有端點測試的完整程式碼,請檢查[儲存庫](https://github.com/oriechinedu/sequelize-with-postgres-tutorial/blob/master/tests/routes.test.js)。 ### 結論 我們已經能夠完成為與資料庫互動的 API 端點編寫測試的過程。在本文的最後部分,我將撰寫有關將 CI/CD 和程式碼覆蓋工具整合到測試環境的文章。在那之前請繼續關注。 如果您對改進文章有任何疑問或建議,請隨時與我聯繫。您也可以透過下面的評論部分分享您的想法。謝謝! _本文最初發表在我的[部落格](https://www.oriechinedu.com/posts/testing-nodejs-express-api-with-jest-and-supertest/)_ --- 原文出處:https://dev.to/nedsoft/testing-nodejs-express-api-with-jest-and-supertest-1km6

Supabase Auth:身分連結、Hooks 和 HaveIBeenPwned 集成

我們很高興地宣布 Supabase Auth 的四項新功能: 1. 身份連結 2. 會話控制 3. 密碼外洩保護 4. 帶有 Postgres 函數的 Auth Hooks {% 嵌入 https://youtu.be/LF8GABnAFyE %} ## 身份連結 當使用者登入時,系統會使用身份驗證方法和登入提供者建立身分。從歷史上看,如果身分與使用者共享相同的經過驗證的電子郵件,[Supabase Auth](https://supabase.com/docs/guides/auth) 會自動將身分連結到使用者。這可以方便地刪除重複的用戶帳戶。然而,一些開發人員還需要靈活地連結不共享相同電子郵件的帳戶。 今天,我們推出身份連結,開發人員可以使用它手動連結兩個單獨的身份。我們為開發人員新增了兩個新端點來管理身分連結流程: 使用者登入後,使用「linkIdentity()」[連結 OAuth 身分:](https://supabase.com/docs/reference/javascript/auth-linkidentity) ``` const { data, error } = await supabase.auth.linkIdentity({ provider: 'google', }) ``` 使用 `unlinkIdentity()` 來[取消連結身分](https://supabase.com/docs/reference/javascript/auth-unlinkidentity): ``` // retrieve all identities linked to a user const { data: { identities }, } = await supabase.auth.getUserIdentities() // find the google identity linked to the user const googleIdentity = identities.find(({ provider }) => provider === 'google') // unlink the google identity from the user const { data, error } = await supabase.auth.unlinkIdentity(googleIdentity) ``` 目前,這些方法支援連結 OAuth 身分。要將電子郵件或電話身分連結到用戶,您可以使用 [updateUser()](https://supabase.com/blog/supabase-auth-identity-linking-hooks#:~:text=can%20use% 20the -,updateUser(),-method.)方法。 預設情況下禁用手動連結。您可以在[儀表板驗證設定](https://supabase.com/dashboard/project/_/settings/auth) 中為您的專案啟用它。 ![如何啟用手動連結](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmsrmiw0ue3q5rshji7v.jpg) > 有關更多訊息,請參閱[身份連結文件](https://supabase.com/docs/guides/auth/auth-identity-linking)。 ## 會話控制 Supabase Auth 從使用者登入應用程式那一刻起管理整個會話生命週期。這涉及以下步驟: 1. 為使用者建立會話。 2. 刷新會話以使其保持活動狀態。 3. 過期或登出時撤銷會話。 對於想要更好地控制使用者會話的開發人員,我們公開了 3 個新設定: - **時間盒使用者會話:** 強制使用者在一段時間間隔後再次登入。 - **不活動逾時:** 如果使用者在一段時間內不活動,則強制使用者重新登入。 - **每個使用者單一會話:** 將使用者限制為單一會話。保留最近的活動會話,並終止所有其他會話。 這些會話控制設定在專業版及以上版本中可用。 ![如何強制每個使用者單一會話](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aov0nw5xch0m4hw97vsg.jpg) > 有關更多訊息,請參閱[會話管理文件](https://supabase.com/docs/guides/auth/sessions)。 ## 密碼外洩保護 由於常見的使用者行為(例如選擇可猜測的密碼或在不同平台上重複使用密碼),密碼本質上可能是不安全的。 儘管 OAuth 和 magiclinks 更安全,但我們認識到密碼將繼續存在。我們希望讓用戶不易陷入潛在的陷阱。為了實現這一目標,我們在 Supabase Auth 中整合了 [HaveIBeenPwned.org](https://haveibeenpwned.com/) _Pwned Passwords API_,以防止使用者使用洩漏的密碼。 > **去圖書館** ℹ️ 我們開源了一個 Go 函式庫,用於與我們在身分驗證伺服器中使用的 [HaveIBeenPwned.org](http://haveibeenpwned.org/) Pwned 密碼 API 互動。查看 [存儲庫](https://github.com/supabase/hibp) 並隨時貢獻! 作為附加步驟,我們新增了為您的使用者指定密碼要求的功能。這可以透過[儀表板:](https://supabase.com/dashboard/project/_/settings/auth) 中專案的身份驗證設定進行配置 ![新增密碼要求](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3o9ax3tudp7v8tba67hd.jpg) > 請參閱[密碼文件](https://supabase.com/docs/guides/auth/passwords) 以了解更多資訊。 ## 驗證掛鉤 我們收到了大量回饋,詢問如何自訂 Auth,例如: - 將自訂聲明新增至存取權杖 JWT - 多次嘗試 MFA 驗證失敗後註銷用戶 - 對密碼驗證嘗試套用自訂規則 我們的目標是保持簡單、無縫的 Supabase Auth 體驗。對於大多數開發人員來說,它應該可以輕鬆工作,而無需自訂。但是,認識到應用程式的多樣性,您現在可以透過 Auth Hook 擴展標準 Auth 功能。 Auth Hooks 只是 Postgres 函數,它們在 Auth 生命週期的關鍵點同步執行,以更改操作的結果。 例如,要使用 Auth Hooks 自訂 JWT 聲明,您可以建立一個 Postgres 函數,該函數接受第一個參數中的 JWT 聲明並傳回您希望 Supabase Auth 使用的 JWT。 假設您正在建立一個遊戲化應用程式,並且希望將用戶的層級作為自訂聲明附加到 JWT: ``` create function custom_access_token_hook(event jsonb) returns jsonb language plpgsql as $$ declare user_level jsonb; begin -- fetch the current user's level select to_jsonb(level) into user_level from profiles where user_id = event->>'user_id'::uuid; -- change the event.claims.level return jsonb_set( event, '{claims,level}', user_level); end; $$ ``` 在資料庫中建立函數後,您只需使用 Supabase Auth 註冊它: ![Auth Hooks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unkgs56o62l8c4kfjzjg.jpg) 目前,您可以為流程中的以下點註冊 Auth Hook: - **自訂存取權杖:** 每次產生新的 JWT 時都會呼叫。 - **MFA 驗證嘗試:** 每次驗證 MFA 因素時都會呼叫,從而可以更好地控制檢測和阻止嘗試。 - **密碼驗證嘗試:** 每次使用密碼登入使用者時都會呼叫,從而可以更好地控制使用者帳戶的安全性。 如果編寫 PL/pgSQL 函數不是您的強項,您始終可以使用 [pg_net](https://supabase.com/docs/guides/database/extensions/pg_net) 向後端 API 發送請求,或使用[plv8]( https://supabase.com/docs/guides/database/extensions/plv8) 透過用JavaScript 編寫函數來更輕鬆地操作JSON。 Auth Hooks 今天可供自架,並將於下個月推出到該平台。如果您需要盡快存取,請透過[支援](https://supabase.help/)與我們聯繫! 那不是全部! Postgres 函數並不是寫鉤子的唯一方法。 Supabase 是 [Standard Webhooks](https://www.standardwebhooks.com/) 的創始貢獻者,這是一組關於輕鬆、安全、可靠地發送和接收 Webhook 的開源工具和指南。當然,Auth Hooks 將在 2024 年第一季支援 Webhooks。 ## 還有一件事… 如果您從一開始就關注我們(https://supabase.com/blog/supabase-auth),您就會知道Supabase Auth 是透過分叉[Netlify 的GoTrue 伺服器](https://github.com)開始的/netlify/gotrue)。從那時起,發生了很多變化,我們已經偏離了上游儲存庫。在這個階段,將專案重新命名為其他名稱是有意義的(提示鼓聲)-Auth。 這僅僅意味著儲存庫將從使用“gotrue”重新命名為“auth”。但別擔心! Docker 映像和庫(如“@supabase/gotrue-js”)將繼續發布,只要當前 v2 版本受支持,您就可以互換使用“@supabase/auth-js”。所有類別和方法都保持不變。這裡沒有重大變化! ## 結論 感謝您閱讀到最後!我們希望您喜歡第 X 週發布的 Supabase Auth 更新:身分連結、會話控制、洩露密碼保護和帶有 Postgres 功能的 Auth Hooks。 我們期待看到您使用這些新功能建立的內容,當然還有您的回饋意見,以使它們變得更好。 ## 更多發布第 X 週 - [第 1 天 - Supabase Studio 更新:AI 助理與使用者模擬](https://supabase.com/blog/studio-introducing-assistant) - [第 2 天 - Edge Functions:節點和本機 npm 相容性 ](https://supabase.com/blog/edge-functions-node-npm) -[第 3 天 - 介紹 Supabase Branching,這是一個針對每個拉取請求的 Postgres 資料庫](https://supabase.com/blog/supabase-branching) - [Postgres語言伺服器:實作解析器](https://supabase.com/blog/postgres-language-server-implementing-parser) - [Supabase 專輯](https://www.youtube.com/watch?v=r1POD-IdG-I) - [Supabase 啟動週 X 黑客松](https://supabase.com/blog/supabase-hackathon-lwx) - [啟動週 X 社群聚會](https://supabase.com/blog/community-meetups-lwx) --- 原文出處:https://dev.to/supabase/supabase-auth-identity-linking-hooks-and-haveibeenpwned-integration-19e1

Edge Functions:Node 和本機 npm 相容性

我們很高興地宣布,[Edge Functions](https://supabase.com/docs/guides/functions) 現在原生支援 npm 模組和 Node 內建 API。您可以將數百萬個流行、常用的 npm 模組直接匯入 Edge Functions 中。 `從 'npm:drizzle-orm/node-postgres' 導入 { drizzle }` ## 將現有 Node 應用程式遷移到 Edge Functions 您可以透過最少的變更將現有的 Node 應用程式遷移到 Supabase Edge Functions。 我們建立了一個示範來展示如何遷移使用 Express、Node Postgres 和 Drizzle 的 Node 應用程式。有關在 Edge Functions 中使用 npm 模組和 Node 內建程式的更多訊息,請參閱[管理依賴項指南](https://supabase.com/docs/guides/functions/import-maps)。 {% 嵌入 https://youtu.be/eCbiywoDORw %} **npm 模組的底層運作原理** 我們執行一個開源 Deno 伺服器來託管 Edge Functions,稱為 [Supabase Edge Runtime](https://supabase.com/blog/edge-runtime-self-hosted-deno-functions)。此自訂版本可協助我們保持 Edge Functions 以相同的方式運作,無論部署在何處 - 在我們的託管平台上、在本地開發中還是在您的自託管環境中。 加入 npm 支援時最大的挑戰是找到適用於所有環境的方法。我們希望保持工作流程接近 Deno CLI 體驗。應該可以直接在原始程式碼中導入 npm 模組,而無需額外的建置步驟。 部署函數時,我們將其模組圖序列化為單一檔案格式([eszip](https://github.com/denoland/eszip))。在託管環境中,所有模組引用都會從 eszip 中載入。這可以防止獲取模組時出現任何額外的延遲以及模組依賴關係之間的潛在衝突。 我們也在本機和自架環境中使用了 eszip 模組載入器,因此我們只需要為所有環境實作一種模組載入策略。作為本地開發的另一個好處,此方法避免了與使用者係統中安裝的 npm 模組的潛在衝突,因為 Edge Function 的 npm 模組是獨立於 eszip 中的。 [重構模組載入器](https://github.com/supabase/edge-runtime/pull/223)修正了一些其他錯誤,例如[邊緣函數錯誤](https://github.com/supabase/cli /issues/1584#issuecomment-1848799355) 當專案中已存在`deno.lock` 檔案時。 ## 您要求的其他一些東西... **區域呼叫** 現在,您可以選擇在執行邊緣函數時指定區域(也許我們將來應該更改名稱)。通常,邊緣函數在最靠近呼叫函數的使用者的區域中執行。但是,有時您希望在靠近 Postgres 資料庫或其他第 3 方 API 的地方執行它,以獲得最佳效能。 功能仍然部署到所有區域。但是,在呼叫過程中,您可以提供“x-region”標頭以將執行限制在特定區域。 **捲曲** ``` # https://supabase.com/docs/guides/functions/deploy#invoking-remote-functions curl --request POST 'https://<project_ref>.supabase.co/functions/v1/hello-world' \ --header 'Authorization: Bearer ANON_KEY' \ --header 'Content-Type: application/json' \ --header 'x-region: eu-west-3' \ --data '{ "name":"Functions" }' ``` **JavaScript** ``` // https://supabase.com/docs/reference/javascript/installing import { createClient } from '@supabase/supabase-js' // Create a single supabase client for interacting with your database const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key') // https://supabase.com/docs/reference/javascript/functions-invoke const { data, error } = await supabase.functions.invoke('hello-world', { body: { name: 'Functions' }, headers: { 'x-region': 'eu-west-3' }, }) ``` > ℹ️查看[區域呼叫指南](https://supabase.com/docs/guides/functions/regional-inspiration)以了解更多詳情。 **更好的指標** 我們在 [Supabase 儀表板](https://supabase.com/dashboard/project/_/functions) 的 Edge Functions 部分中加入了更多指標:它現在顯示 CPU 時間和使用的記憶體。我們也按 HTTP 狀態碼細分了呼叫。 這些變更可協助您發現邊緣功能的任何問題並採取行動。 > ℹ️ 請參閱 Edge Functions 的[日誌記錄和指標指南](https://supabase.com/docs/guides/functions/debugging) 以了解更多資訊。 ![使用視覺化範例](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ki4pk0w0ykpa9i2c47q.jpg) **使用 Sentry 追蹤錯誤** 我們 Sentry 的朋友最近發布了官方的 [Sentry SDK for Deno](https://deno.land/x/[email protected])。有了這個,現在可以輕鬆追蹤 Sentry 邊緣函數中的錯誤和異常。 以下是一個簡單的範例,說明如何處理函數中的異常並將其傳送到 Sentry。 ``` import * as Sentry from 'https://deno.land/x/sentry/index.mjs' Sentry.init({ dsn: _DSN_, integrations: [], // Performance Monitoring tracesSampleRate: 1.0, // Set sampling rate for profiling - this is relative to tracesSampleRate profilesSampleRate: 1.0, }) // Set region and execution_id as custom tags Sentry.setTag('region', Deno.env.get('SB_REGION')) Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID')) Deno.serve(async (req) => { try { const { name } = await req.json() const data = { message: `Hello ${name}!`, } return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } }) } catch (e) { Sentry.captureException(e) return new Response(JSON.stringify({ msg: 'error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }) } }) ``` ## 下一步是什麼 NPM 支援是 Edge Functions 最受歡迎的功能之一。如果您之前因缺乏支援而無法使用 Edge Functions,我們希望此更新能夠吸引您[再試一次](https://supabase.com/dashboard/project/_/functions)。如果您遇到任何問題,我們只需[一個支援請求](https://supabase.help/)。 對於現有的 Edge Functions 用戶來說,區域呼叫、更好的指標和錯誤處理只是接下來會發生的事情的一瞥。我們繼續迭代平台穩定性並對邊緣功能可以使用的資源設定自訂限制。請留意新的一年的另一篇文章。 ## 更多發布第 X 週 - [第 1 天 - Supabase Studio 更新:AI 助理與使用者模擬](https://supabase.com/blog/studio-introducing-assistant) - [pg_graphql:現在支援 Postgres 函式](https://supabase.com/blog/pg-graphql-postgres-functions) - [Postgres語言伺服器:實作解析器](https://supabase.com/blog/postgres-language-server-implementing-parser) - [Supabase 設計如何運作](https://supabase.com/blog/how-design-works-at-supabase) - [Supabase 專輯](https://www.youtube.com/watch?v=r1POD-IdG-I) - [Supabase 啟動週 X 黑客松](https://supabase.com/blog/supabase-hackathon-lwx) - [啟動週 X 社群聚會](https://supabase.com/blog/community-meetups-lwx) --- 原文出處:https://dev.to/supabase/edge-functions-node-and-native-npm-compatibility-77f

您應該知道的 10 個高級 JavaScript 技巧!

歡迎來到 JavaScript 的奇妙世界,在這裡,程式設計與魔法相遇!如果您曾經感受到在網路上建立內容的快感,但想知道其背後隱藏的策略,那麼您來對地方了。✨🚀 在這篇部落格中,我們將穿越 JavaScript 領域,揭開複雜的神秘面紗,擁抱簡單。沒有令人困惑的術語——只有簡單的英語解釋和逐步說明。無論您是編碼新手還是經驗豐富的開發人員,請加入我們,我們會發現 10 個高級 JavaScript 技巧,助您一臂之力_“啊哈!”_ ## 1. DESTRUCTURING ASSIGNMENT 賦值解構是一種簡潔的擷取方式 來自陣列或物件的值並將它們分配給變數。 它簡化了您的程式碼並提高了可讀性。為了 陣列,可以使用括號表示法,並且可以使用 物件的大括號。 ![破壞](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at1hxowbpsxzgi2gln6j.jpeg) --- ## 2. SPREAD SYNTAX 您可以使用擴充語法來擴充元素 一個陣列或一個物件的屬性到另一個物件中 這對於製作副本、合併物件以及 將多個參數傳遞給函數。 ![傳播語法](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoqllndthqgr0n931thc.jpeg) --- ## 3. CURRYING 柯里化是一種函數式程式設計技術,其中 接受多個參數的函數被轉換 分成一系列函數,每個函數取一個參數 這允許更好地重複使用和組合 程式碼。 ![柯里化](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isp1ssqnxde6uvodqr9j.jpeg) --- ## 4. MEMOIZATION 這是一種快取技術,用於儲存結果 昂貴的函數呼叫並避免不必要的 重新計算。 它會顯著降低長期性能 遞歸或消耗函數。 ![記憶](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xw1jdu75vkjev3kw8osy.jpeg) --- ## 5. PROMISES AND ASYNC/AWAIT Promise 和 Async/Await 對於處理至關重要 更優雅地非同步操作並使程式碼更優雅 更具可讀性和可維護性。 它們有助於避免地獄般的回調並改善錯誤處理。 ![Promises-Async/Await](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oq6276u1rilbozbfpo4u.jpeg) --- ## 6. CLOSURES 閉包是記住環境的函數 他們被創造出來,即使那個環境沒有 更容易存取。 它們對於建立私有變數和 行為封裝。 ![關閉](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iy1zkeqx9ta5gqormq0p.jpeg) --- ## 7. FUNCTION COMPOSITION 函陣列合是將兩個或兩個函陣列合起來的過程 更多功能建立新功能。 它鼓勵程式碼重複使用並幫助建立 轉變一步一步複雜。 ![函陣列合](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6g9kzxezkemutb1zvuvd.jpeg) --- ## 8. PROXY 代理物件允許您建立自訂行為 用於基本的物件操作。它允許你攔截 並修改物件操作。 '物件,例如 存取屬性、分配和呼叫方法。 ![代理](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/je32r9eu2y3wf5rrm50b.jpeg) --- ## 9. EVENT DELEGATION 事件委託是一種附加事件委託的技術 父級的單一事件偵聽器而不是多個 每個孩子的聽眾。記憶體使用情況並改善 效能,特別是對於大型列表或動態列表 產生的內容。 ![事件委託](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar60xpbcri5931giv2ze.jpeg) --- ## 10. WEB WORKERS Web Workers 允許您在以下位置執行 JavaScript 程式碼 背景,與主線程一起。 它們對於卸載 CPU 密集型任務很有用, 避免 UI 掛起並提高效能回應能力。 ![Web-Workers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c965v7g8kgh9y1rpp528.jpeg) --- ## 結論 好了,各位研究人員!😊 我們一起穿越了 JavaScript 星系,揭示了 10 種乍看之下很神奇的技術。但現在,有了一點理解和熱情,您就可以自信地應用這些編碼咒語了。 如果您喜歡這個神奇的旅程,請不要忘記點擊_關注按鈕_以了解更多編碼冒險。當然,您的評論是讓這個社區蓬勃發展的秘密武器。請在下面分享您的想法、問題或您自己的 JavaScript 技巧。讓我們繼續對話吧! 感謝您加入這次冒險。下次見,祝您編碼愉快! 🚀💻✨ --- 原文出處:https://dev.to/big_smoke/10-advanced-javascript-tricks-you-should-know--1ofj

🛠️6 個工具,利用 AI 做出你的全端應用程式 🤖

_「現在是2021 年了,我的飛行汽車在哪裡?」_ - Joel Spolsky(Stack Overflow 和Trello 的建立者)用這句話來表達他對Web 開發仍然與20 年前幾乎相同的感覺的幻滅。 但今天,有了 GPT,我們就可以再問這個問題了。我們看到了所有這些花哨的推文和演示,但是**當我需要啟動一個新的全端 Web 應用程式時**,這對我作為開發人員意味著什麼?我真的必須經歷“npm create vite my-new-app”,並再次從空白頁面開始嗎? 最後的答案是「否」——你可以使用很多很酷的東西來讓你的生活更輕鬆。它可能還不是超音速德羅寧,但它至少肯定是在地面上盤旋。 讓我們探討一下今天的 AI 場景為我們提供了什麼,以便更輕鬆地啟動和建立全端 Web 應用程式: ## 🐝 🤖 MAGE - 一分鐘內從單一提示到全端、React 和 Node.js 應用程式(免費使用!) ![MAGE 行動](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9chayxjmuab1e85evc1.gif) [MAGE](https://usemage.ai/) (*Magic App GEnerator*) 可能是最容易使用的 AI 編碼代理 - 一切都透過 Web 介面進行,**您所要做的就是輸入您要建立的應用程式的簡短描述**。這樣,MAGE 將在由 [Wasp](https://wasp-lang.dev/) 提供支援的 React、Tailwind、Node.js 和 Prisma 中產生完整的全端程式碼庫,您可以免費下載。 MAGE 最好的部分是**它是完全開源且完全免費使用** - 您所需要做的就是[使用您的 GitHub 登入](https://usemage.ai/),然後您就可以開始建立應用程式! MAGE [於7 月在Product Hunt 上推出](https://www.producthunt.com/products/wasp-lang-alpha#gpt-webapp-generator-for-react-node-js),從那時起就被用來建立近 30,000 個應用程式。 ## 📟 Aider - 終端機中的 AI 配對程式設計師 ![Aider 示範](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1g8iir36pbnja90cldn1.gif) 在您使用 MAGE 建立應用程式的 v1 版並獲得基本功能後,您可能會想要加入更多功能。為什麼不使用人工智慧來實現這一點呢?這就是 Aider 發揮作用的地方! Aider 的超能力在於您可以將其插入任何現有專案並開始使用!這感覺就像與坐在您旁邊的開發人員同事聊天 - 只需描述您的下一個功能,Aider 將盡力實現它,同時提供流程的所有詳細訊息,並自動向您的存儲庫加入新的提交!多麼酷啊? 您可以了解更多有關 Aider 的資訊並在這裡嘗試一下:https://github.com/paul-gauthier/aider ## 🦀 🚀 Shuttle AI - 使用 GPT 在 Rust 中建立後端! ![穿梭示範](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n2bw3i79f4ojhwdpky1.png) 當您聽到“網頁應用程式”這個詞時,我們大多數人都會立即想到 JavaScript。雖然對於前端來說這在很大程度上是正確的,但我們可以用我們喜歡的任何技術來建立後端! 除了 Python、Java 和 PHP 等常見的嫌疑犯之外,Rust 又如何呢?它是開發人員最喜愛的語言之一,它不應該只用於低階演算法。 Shuttle AI 讓這一切成為可能 - 他們強大的基於 Rust 的框架已經使建置和部署後端變得容易,而頂部的 AI 使其變得輕而易舉! 在這裡了解更多:https://www.shuttle.rs/ai ## ⚡️📦 Supabase AI - 再見,複雜的 SQL 查詢 ![Supabase 示範](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzydppmhtizqx4poar5t.png) [Supabase](https://supabase.com/) 是為您的全端應用程式啟動和執行資料庫的最佳方法之一,除此之外您還可以獲得大量功能!由於它專門用於 Postgresql,這意味著您偶爾需要編寫一些 SQL。為什麼不從人工智慧得到一些幫助呢? Supabase 因其美觀且用戶友好的儀表板(帶有整合 SQL 編輯器)而聞名,現在他們透過加入自己的 AI 代理使其變得更好。要求它建立新的表和索引,甚至編寫資料庫函數! 在這裡了解更多:https://supabase.com/blog/supabase-studio-3-0 ## 👁️ 🧑‍✈️Visual Copilot - 將 Figma 設計編碼 ![figma 示範](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1jhtqsqtj59wprziesa.png) 如果您曾經從設計師那裡獲得 Figma 設計講義,然後您的任務是用它來實現 UI,您是否想過是否有一種方法可以自動化此操作?這就是 Visual Copilot 所追求的! 只需點擊一下,並給出 Figma 設計,Visual Copilot 就會為其產生前端程式碼!它將盡最大努力使其具有響應性並保持程式碼整潔和可重複使用。 它目前可作為 [Figma 社群插件](https://www.figma.com/community/plugin/747985167520967365/builder-io-ai-powered-figma-to-code-react-vue-tailwind-more) 。 ## ✈️ 🤖 GPT Pilot - 使用協作 AI 啟動新應用程式 ![試辦示範](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/az5mkurpyu80dtvthxdy.png) GPT Pilot 是專門用於從頭開始建立新應用程式的編碼代理程式。它獨特的做法是它與開發者合作——每當遇到困難時,它都會尋求你的幫助! 在內部,它由多個代理組成,這些代理一起協作並經歷應用程式開發的不同階段 - 從產品所有者和架構師到 DevOps 和開發人員! ![試辦系統](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vro6qo3khbskfxxfv0h.jpg) 這是另一個完全開源的解決方案,最近受到了開發人員的喜愛,並多次出現在 GitHub 趨勢排行榜上。 了解更多並在這裡嘗試一下:https://github.com/Pythagora-io/gpt-pilot ## 概括 ![換行](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/padyzsbgaec1ophqtqep.gif) 這就是一個包裝!還有更多的人工智慧工具,而且每天都有新的工具出現,但在本概述中,我們試圖專注於您今天可以用來啟動新的網路應用程式的工具。 希望您發現這很有幫助,並學到了一些可能派上用場的新東西!我也很想在評論中聽到您的意見 - 您最喜歡的 Web 開發人工智慧工具是什麼,無論是您每天使用的工具還是只是感到興奮的工具,接下來我們應該介紹什麼? --- 原文出處:https://dev.to/matijasos/6-tools-to-kickstart-your-full-stack-app-with-ai-4oh3

使用 VSCode 更快輸入程式碼的技巧分享

VSCode 寫程式技巧分享! ## 更聰明地複製、貼上 我見過人們透過執行以下操作來複製貼上程式碼: 1. 將滑鼠遊標移至單字開頭。 2. 按住左鍵點選。 3. 一直拖曳到單字最後。 4. 釋放左鍵點選。 5. 右鍵點選所選內容。 6. 按一下「複製」。 7. 在 VS Code 的檔案總管中捲動以尋找目標檔案。 8. 點選目標檔案。 9. 將遊標移到檔案中的所需位置。 8. 右鍵點選目標位置。 9. 按一下「貼上」。 這是一個有點慢的過程。特別是如果您需要多次應用此操作...改進複製貼上的一些方法是: - 使用“CTRL + C”進行**複製**,使用“CTRL + V”進行**貼上**。 - 使用“CTRL + SHIFT + 左/右箭頭”**增加/減少單字選擇**。 - 使用“SHIFT + 左/右”箭頭**按字元增加/減少選擇**。 - 點擊 VS Code 中的一行程式碼並按下「CTRL + X」將**將該行放入剪貼簿**。在任何地方使用“CTRL + V”都會**在其中插入該行程式碼**。 - 使用「ALT + 向上/向下箭頭」**將一行程式碼向上/向下移動**一個位置。 更聰明地複製貼上也意味著更聰明地導航。 ## 更聰明地導航 使用組合鍵“CTRL + P”,而不是手動瀏覽資源管理器窗格。這樣,您可以按名稱搜尋文件。這是一個“智能”搜尋,意味著它不僅會查找包含搜尋文本的單詞,還會查找組合,例如“prodetcon”還將查找“project-details-container.component.ts”。使用「CTRL + P」比看到有人在檔案總管窗格中掙扎要快得多,這本身就是一種痛苦(雙關語)。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgi4edfc61mjln700yon.gif) 不要透過捲動來尋找文件內的某些程式碼,而是使用以下組合鍵: - `CTRL + G`:轉到行 - `CTRL + F`:在檔案中搜尋(使用`ENTER`鍵導航到下一個符合專案) - `CTRL + 點選類別/函數/等`:轉到所述類別/函數/等的定義。 使用“CTRL + TAB”在上次開啟的檔案和目前開啟的檔案之間切換(或使用“TAB”進一步切換到其他開啟的檔案)。這比將遊標移到工作列、查找正確的標籤並點擊它打開要快得多。 > 注意:在 VS Code 中,以這種方式在開啟的檔案之間進行切換非常有效率。另外,在 Windows 中使用「ALT + TAB」在開啟的視窗之間切換。 ## 更聰明地重新命名 不要自己重命名變數的每一次出現。它既耗時又容易出錯。相反,請轉到該變數的定義並按“F2”,重命名它,然後按“ENTER”。這將改變每一次發生的情況。這不僅適用於變數,也適用於函數、類別、介面等。這也適用於跨文件。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jls5prhd81ua6o24w6hl.gif) ## 使用 Emmet [Emmet](https://emmet.io/) 是一個內容/程式碼輔助工具,可以更快、更有效率地編寫程式碼。它是[VS Code 的標準](https://code.visualstudio.com/docs/editor/emmet),因此不需要任何插件。這個概念很簡單:您開始輸入 Emmet 縮寫,按下“TAB”或“ENTER”,就會出現該縮寫的完整 Emmet 片段。 Emmet 縮寫的範例可以是「.grid>.col*3」。當您按下「TAB」或「ENTER」時,VS Code 會為您填寫整段程式碼: ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wt5s8wb3splmpvylkhm.gif) Emmet 的一大優點是您也可以產生 [“lorem ipsum” 文字](https://docs.emmet.io/abbreviations/lorem-ipsum/)。例如,`ul>li*4>lorem4`將產生一個包含 4 個元素的無序列表,每個清單專案包含 4 個隨機單字。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3pgcocuj4r7nfbt6wvyb.gif) ## 使用格式化程式 使用 VS Code 中的程式碼格式化程式來格式化程式碼。我強烈推薦[Prettier](https://prettier.io/docs/en/)。 使用程式碼格式化程式的好處之一是它還可以「美化」您的程式碼。因此,如果您從根本沒有佈局的地方複製貼上程式碼,您可以點擊格式組合鍵(“CTRL + ALT + F”)等等,您的程式碼現在“美化”了,更重要的是,可讀了。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/505nwj0kpv7eotq5e8ns.gif) > 注意:一個好的提示是在儲存時套用格式。您可以在設定中變更此設定(尋找「儲存時格式」)。 格式化不僅對你自己有用,而且對整個團隊有用,因為它強制團隊的程式碼更加一致。看看我的另一篇文章[在Angular 專案中強制執行前端指南](https://dev.to/kinginit/enforcing-front-end-guidelines-in-an-angular-project-4199) 了解更多資訊關於它。 ## 使用程式碼片段 程式碼片段是模板,可以更輕鬆地編寫重複的程式碼片段,例如 for 迴圈、while 語句等。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9v9g9v8mhlojm00aex6g.gif) 透過使用程式碼片段,您可以透過輸入最少的內容輕鬆建立程式碼區塊。您可以使用內建的程式碼片段,使用提供程式碼片段的擴展,甚至建立您自己的程式碼片段! 內建程式碼片段提供了多種語言的模板,例如 TypeScript、JavaScript、HTML、CSS 等。例如,您可以使用它輕鬆建立「switch」語句,如上所示。 VS Code Marketplace 有多個擴充功能可以提供您程式碼片段。例如 [Angular 片段](https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2)、[Tailwind UI 片段](https://marketplace.visualstudio.com/items?itemName=evondev.tailwindui-marketplace.visualstudio.com/items?itemName=evondev.tailwindui-evondev.tailwindui-片段)、[Bootstrap 片段](https://marketplace.visualstudio.com/items?itemName=thekalinga.bootstrap4-vscode) 等。 最後,您可以建立自己的片段。您可以為特定語言建立全域程式碼片段,也可以建立特定於專案的程式碼片段。我不會在這裡詳細介紹任何細節,但請查看有關[如何建立自己的片段](https://code.visualstudio.com/docs/editor/userdefinesnippets#_create-your-own-snippets)。 ## 利用“量子打字” 我將其稱為“量子輸入”,因為這確實加快了您在 VS Code 中輸入程式碼的速度。這都是關於多重選擇的。當您需要更改或新增文字到多行時,VS Code 允許您透過選擇這些多行並同時開始在這些行上鍵入來完成此操作。 按住“SHIFT + ALT”並拖曳多條線以進行選擇。您將看到這些行上出現多個鍵入遊標。只需開始輸入,文字就會同時加入。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nl37ca8jwo8sfnm07j0p.gif) 如果您想將相同的文字新增至多個位置但它們不對齊,您可以按住「ALT」同時按一下您要鍵入相同文字的所有位置。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/loqu6id3968iilj1o1jl.gif) 您也可以按住“ALT”並同時選擇多個單字。無需單擊某個位置,只需拖曳進行選擇,然後釋放左鍵單擊或雙擊即可選擇單個單字,同時按住“ALT”鍵。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o05eg38ejzcxhtotlza9.gif) ## 快速環繞選擇 程式碼通常必須用方括號、圓括號或大括號括起來。或某些內容需要用引號(單引號或雙引號)引起來。為此,人們通常會轉到起始位置,輸入起始括號,將遊標移到結束位置,然後輸入結束括號。更有效的方法是選擇需要包圍的零件,然後簡單地鍵入起始括號。 VS Code 會夠聰明,知道整個部分需要被包圍。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upt3uxf00b9j9ujoetq4.gif) 這適用於 `(`、`{`、`[`、`<`、`'` 和 `"`。 ## 利用 VS Code 重構技巧 您可以使用 VS Code 自動重構程式碼片段。例如,您可以讓 VS Code 為您產生它們,而不是編寫自己的 getter 和 setter。 要重構某些內容,只需選擇需要重構的內容,右鍵單擊,然後單擊“重構...”,甚至更快:使用“CTRL + SHIFT + R”。 根據您所在的文件,VS Code 可以為您提供多種重構。例如,對於 TypeScript,您可以使用「提取函數」、「提取常數」或「產生 get 和 set 存取器」。請參閱 [此處](https://code.visualstudio.com/docs/typescript/typescript-refactoring) 的 TypeScript 完整清單。 ## 使用正規表示式搜尋和替換 正規表示式 (RegEx) 可能是開發人員工具包中非常強大的工具,值得您花時間更好地熟悉它們。您不僅可以在自己的程式碼中使用它(例如,驗證模式、字串替換等),還可以在 VS Code 中使用它進行高級搜尋和替換。 ### 例子 在您所在的專案中,一些 CSS 選擇器以 `app-` 開頭並以 `-container` 結尾。由於新的指導方針,他們希望您將後綴“-container”更改為“-wrapper”。您可以嘗試進行簡單的搜尋和替換,方法是尋找“-container”並將其替換為“-page”,但是當您進行替換時,您會看到某些出現的內容已被替換,而這本不應該是這樣的(例如,名為“.unit-container-highlight”的 CSS 選擇器變成“.unit-wrapper-highlight”)。 透過RegEx,我們可以進行更細粒度的搜尋。使用捕獲組,我們可以提取我們想要保留的單詞,同時替換其餘的單詞。正規表示式看起來像是「app-([a-z\-]+)-container」。我們想要替換結果,使其以“-page”結尾。替換字串將類似於“app-$1-wrapper”。只要確保您選取了“使用正規表示式”即可。 > 注意:儘管正則表達式允許更細粒度的搜尋,但在進行實際替換之前請檢查搜尋窗格中的結果! ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jojfb84q3ir9c2js61c7.png) 您可以透過允許搜尋僅應用於某些文件來獲得更多控制。範例可以只是 HTML 檔案(`*.html`),甚至只是整個資料夾(`src/app/modules`)。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1m03sd4p8nffhga5jveb.png) 如果您想在搜尋之前嘗試 RegEx 以確保它是正確的,請使用線上 RegEx 測試器,例如 [Regex101](https://regex101.com/)。如果您沒有或很少有 RegEx 經驗,請查看 [https://regexlearn.com/](https://regexlearn.com/learn/regex101)。 ## 使用工具自動化單調的工作 有時我們必須做一些單調的工作,例如建立模擬資料、為類別中的每個欄位建立函數、根據介面的屬性建立 HTML 清單專案等。俗話說: > 更聰明地工作,而不是更努力工作! 使用工具來自動化此類單調的工作,而不是自己完成所有繁瑣的工作。我常用的工具有: - [NimbleText](https://nimbletext.com/live):根據給定格式將行輸入轉換為特定輸出。 - [Mockaroo](https://www.mockaroo.com/):產生模擬資料並以多種格式(JSON、CSV、XML 等)輸出。 - [JSON Generator](https://json-generator.com/):也產生模擬資料,但專門針對 JSON。它有點複雜,但它允許定制結果。 使用 NimbleText 的一個很好的例子是基於幾個欄位在 HTML 中建立整個表單。我們有一個要在表單中顯示的欄位清單。每個欄位都有一個標籤和一個輸入。讓我們建立一些資料供 NimbleText 進行轉換: ``` first name, text last name, text email, email street, text number, number city, text postal code, text ``` 這裡我們有 7 行和 2 列。每行代表表單欄位。第一列是標籤的名稱,第二列是 HTML 輸入的類型。 在 NimbleText 中,我們保留設定不變(列分隔符號“,”和行分隔符號“\n”)。 每個表單欄位都應該位於類別為「.form-field」的「div」中,其中包含帶有文字的「label」和表單欄位的「input」。 NimbleText 的模式如下: ``` <div class="form-field">   <label for="<% $0.toCamelCase() %>"><% $0.toSentenceCase() %>:</label>   <input id="<% $0.toCamelCase() %>" type="$1"/> </div> ``` 當我們查看輸出時,我們發現**大量**工作已經為我們完成: ``` <div class="form-field">   <label for="firstName">First name:</label>   <input id="firstName" type="text"/> </div> <div class="form-field">   <label for="lastName">Last name:</label>   <input id="lastName" type="text"/> </div> <div class="form-field">   <label for="email">Email:</label>   <input id="email" type="email"/> </div> <div class="form-field">   <label for="street">Street:</label>   <input id="street" type="text"/> </div> <div class="form-field">   <label for="number">Number:</label>   <input id="number" type="number"/> </div> <div class="form-field">   <label for="city">City:</label>   <input id="city" type="text"/> </div> <div class="form-field">   <label for="postalCode">Postal code:</label>   <input id="postalCode" type="text"/> </div> ``` 因此,盡可能發揮創意並使用這些工具。 ## 結論 在 VS Code 中更快編碼取決於了解快捷鍵並充分利用 IDE 的強大功能。以下是所提及內容的快速總結: 1. 使用快捷鍵進行複製貼上。 2. 透過搜尋取代手動導航,導航更有效率。 3. 使用“F2”重新命名,而不是手動執行。 4. 使用 Emmet。 5. 使用格式化程式來獲得整潔的大綱(以及其他優點)。 6. 使用程式碼片段。 7. 量子型。 8. 使用VS Code重構。 9. RegEx 可以幫助您進行搜尋和取代。 10. 使用NimbleText等工具將單調的工作自動化。 我希望您喜歡閱讀本文。如果您知道有人可能需要一些幫助來更快地編碼,請隨時分享這篇文章! 如果您有任何疑問,請隨時與我們聯繫!謝謝! --- 原文出處:https://dev.to/kinginit/how-to-code-faster-vs-code-edition-4pa