Jadual Kandungan
Pemprosesan pengesahan
Prasyarat
Kebergantungan
Menyediakan struktur direktori dan persekitaran pembangunan
Tetapan pangkalan data
Mengintegrasikan Skema dan Parser dengan Graphql Server
model
Parser
pelayan
API ujian
Mutasi untuk pengguna berdaftar
Mutasi log masuk
Pertanyaan untuk pengguna individu
Meringkaskan
Rumah hujung hadapan web tutorial css Let ' s Buat API Pengesahan Sendiri dengan NodeJs dan Graphql

Let ' s Buat API Pengesahan Sendiri dengan NodeJs dan Graphql

Apr 02, 2025 am 04:22 AM

Mari buat API Pengesahan kita sendiri dengan NodeJs dan Graphql

Pengesahan adalah salah satu tugas yang paling mencabar untuk pemaju baru ke GraphQL. Terdapat banyak pertimbangan teknikal yang terlibat, termasuk memilih ORM yang mudah ditetapkan, bagaimana untuk menghasilkan kata laluan token dan hash yang selamat, dan juga perpustakaan HTTP yang digunakan dan cara menggunakannya.

Artikel ini memberi tumpuan kepada pengesahan tempatan . Ini mungkin cara yang paling popular untuk laman web moden untuk mengendalikan pengesahan, yang dicapai dengan meminta e -mel dan kata laluan pengguna (berbanding dengan penggunaan Google Authentication).

Di samping itu, artikel ini menggunakan Apollo Server 2, JSON Web Tokens (JWT) dan Sequelize Orm untuk membina API Pengesahan Node.js.

Pemprosesan pengesahan

Log masuk ke sistem:

  • Pengesahan mengenal pasti atau mengesahkan pengguna.
  • Membenarkan pengesahan laluan (atau bahagian aplikasi) yang boleh diakses oleh pengguna yang disahkan.

Langkah -langkah untuk melaksanakan proses ini adalah seperti berikut:

  1. Pengguna mendaftar dengan kata laluan dan e -mel.
  2. Kelayakan pengguna disimpan dalam pangkalan data.
  3. Selepas pendaftaran selesai, pengguna akan diarahkan ke halaman log masuk.
  4. Selepas pengesahan, pengguna akan diberikan akses kepada sumber tertentu.
  5. Status pengguna disimpan dalam mana -mana medium penyimpanan penyemak imbas (misalnya, localStorage, cookies, sesi) atau dalam JWT.

Prasyarat

Sebelum anda pergi lebih mendalam, berikut adalah beberapa langkah yang perlu anda ikuti.

  • Node.js 6 atau lebih tinggi
  • Benang (disyorkan) atau npm
  • Graphql Playground
  • Asas Graphql dan Node.js
  • ... hati yang mencari pengetahuan!

Kebergantungan

Berikut adalah senarai panjang, mari kita mulakan:

  • Server Apollo : Pelayan GraphQL Sumber Terbuka yang serasi dengan mana -mana jenis klien GraphQL. Dalam projek ini, kami tidak akan menggunakan Express sebagai pelayan kami. Sebaliknya, kami akan memanfaatkan keupayaan pelayan Apollo untuk mendedahkan API GraphQL kami.
  • BCRYPTJS : Kami mahu hash kata laluan pengguna ke dalam pangkalan data kami. Itulah sebabnya kami akan menggunakan Bcrypt. Ia bergantung pada antara muka GetRandomValues ​​API Crypto Web untuk mendapatkan nombor rawak yang selamat.
  • Dotenv : Kami akan menggunakan dotenv untuk memuatkan pembolehubah persekitaran dari fail .env kami.
  • JSONWEBTOKEN : Selepas log pengguna masuk, setiap permintaan berikutnya akan mengandungi JWT, yang membolehkan pengguna mengakses laluan, perkhidmatan, dan sumber yang dibenarkan menggunakan token. JsonWebtoken akan digunakan untuk menjana JWTS, yang digunakan untuk mengesahkan identiti pengguna.
  • Nodemon : Alat yang membantu membangunkan aplikasi berasaskan nod dengan memulakan semula aplikasi nod secara automatik apabila perubahan direktori dikesan. Kami tidak mahu pelayan ditutup dan bermula setiap kali kod berubah. Nodemon memeriksa perubahan dalam aplikasi kami setiap kali dan secara automatik memulakan semula pelayan.
  • MySQL2 : Node.js 'SQL Client. Kami memerlukannya untuk menyambung ke pelayan SQL kami supaya kami dapat menjalankan penghijrahan.
  • Sequelize : Sequelize adalah nod berasaskan janji yang digunakan dalam Postgres, MySQL, MariaDB, SQLite dan Microsoft SQL Server. Kami akan menggunakan Sequelize untuk menghasilkan migrasi dan model kami secara automatik.
  • Sequelize CLI : Kami akan menggunakan CLI Sequel untuk menjalankan perintah Sequel. Pasangnya secara global di terminal menggunakan benang tambah-global sekuel-cli.

Menyediakan struktur direktori dan persekitaran pembangunan

Mari buat projek baru. Buat folder baru dan buat perkara berikut di dalamnya:

 <code>yarn init -y</code>
Salin selepas log masuk

Bendera -Bendera bermakna kita memilih ya untuk semua isu benang init dan gunakan nilai lalai.

Kami juga harus meletakkan fail pakej.json dalam folder, jadi mari pasang kebergantungan projek:

 <code>yarn add apollo-server bcryptjs dotenv jsonwebtoken nodemon sequelize sqlite3</code>
Salin selepas log masuk

Seterusnya, mari tambahkan Babel ke persekitaran pembangunan kita:

 <code>yarn add babel-cli babel-preset-env babel-preset-stage-0 --dev</code>
Salin selepas log masuk

Sekarang, mari kita konfigurasikan Babel. Jalankan sentuhan .babelrc di terminal. Ini akan membuat dan membuka fail konfigurasi Babel di mana kami akan menambah yang berikut:

 <code>{ "presets": ["env", "stage-0"] }</code>
Salin selepas log masuk

Lebih baik jika pelayan kami memulakan dan memindahkan data. Kami boleh melakukan ini secara automatik dengan mengemas kini Package.json dengan yang berikut:

 <code>"scripts": { "migrate": " sequelize db:migrate", "dev": "nodemon src/server --exec babel-node -e js", "start": "node src/server", "test": "echo \"Error: no test specified\" && exit 1" },</code>
Salin selepas log masuk

Inilah fail Pakej.JSON Lengkap semasa kami:

 <code>{ "name": "graphql-auth", "version": "1.0.0", "main": "index.js", "scripts": {  "migrate": " sequelize db:migrate",  "dev": "nodemon src/server --exec babel-node -e js",  "start": "node src/server",  "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": {  "apollo-server": "^2.17.0",  "bcryptjs": "^2.4.3",  "dotenv": "^8.2.0",  "jsonwebtoken": "^8.5.1",  "nodemon": "^2.0.4",  "sequelize": "^6.3.5",  "sqlite3": "^5.0.0" }, "devDependencies": {  "babel-cli": "^6.26.0",  "babel-preset-env": "^1.7.0",  "babel-preset-stage-0": "^6.24.1" } }</code>
Salin selepas log masuk

Sekarang persekitaran pembangunan kami ditubuhkan, mari kita beralih ke pangkalan data, kami akan menyimpan perkara di sana.

Tetapan pangkalan data

Kami akan menggunakan MySQL sebagai pangkalan data kami dan menggunakan Orm Sequelize untuk pemetaan relasi. Run Sequelize init (dengan asumsi anda telah memasangnya secara global sebelum ini). Perintah ini harus membuat tiga folder: /config /model dan /migrasi. Pada masa ini, struktur direktori projek kami terbentuk.

Mari kita konfigurasikan pangkalan data kami. Pertama, buat fail .env dalam direktori root projek dan tampal yang berikut:

 <code>NODE_ENV=development DB_HOST=localhost DB_USERNAME= DB_PASSWORD= DB_NAME=</code>
Salin selepas log masuk

Kemudian pergi ke folder /konfigurasi kami hanya membuat dan menamakan semula fail config.json di dalamnya ke config.js. Kemudian, letakkan kod berikut ke dalamnya:

 <code>require('dotenv').config() const dbDetails = { username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, host: process.env.DB_HOST, dialect: 'mysql' } module.exports = { development: dbDetails, production: dbDetails }</code>
Salin selepas log masuk

Di sini kita membaca butiran pangkalan data yang kita tetapkan dalam fail .env. Process.env adalah pemboleh ubah global yang disuntik oleh nod untuk mewakili keadaan semasa persekitaran sistem.

Mari kita kemas kini butiran pangkalan data kami dengan data yang sesuai. Buka pangkalan data SQL dan buat jadual bernama Graphql_Auth. Saya menggunakan Laragon sebagai pelayan tempatan saya dan menggunakan phpMyAdmin untuk menguruskan jadual pangkalan data.

Tidak kira apa yang anda gunakan, kami perlu mengemas kini fail .env dengan maklumat terkini:

 <code>NODE_ENV=development DB_HOST=localhost DB_USERNAME=graphql_auth DB_PASSWORD= DB_NAME=</code>
Salin selepas log masuk

Mari kita konfigurasi sekuel. Buat fail .seakeSeelizerc dalam direktori root projek dan tampal yang berikut:

 <code>const path = require('path') module.exports = { config: path.resolve('config', 'config.js') }</code>
Salin selepas log masuk

Sekarang mari kita mengintegrasikan konfigurasi kita ke dalam model. Pergi ke folder index.js dalam /model dan edit pembolehubah konfigurasi.

 <code>const config = require(__dirname '/../../config/config.js')[env]</code>
Salin selepas log masuk

Akhirnya, mari kita tulis model kami. Untuk projek ini, kami memerlukan model pengguna. Mari kita gunakan Sequelize untuk menghasilkan model secara automatik. Inilah yang perlu kita jalankan di terminal untuk menetapkannya:

 <code>sequelize model:generate --name User --attributes username:string,email:string,password:string</code>
Salin selepas log masuk

Mari edit model yang dicipta untuk kita. Pergi ke user.js dalam /model folder dan tampal yang berikut:

 <code>'use strict'; module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', {  username: {   type: DataTypes.STRING,  },  email: {   type: DataTypes.STRING,   },  password: {   type: DataTypes.STRING,  } }, {}); return User; };</code>
Salin selepas log masuk

Di sini kami membuat sifat dan bidang untuk nama pengguna, e -mel, dan kata laluan. Mari jalankan penghijrahan untuk menjejaki perubahan dalam skema kami:

 <code>yarn migrate</code>
Salin selepas log masuk

Sekarang mari kita tulis corak dan parser.

Mengintegrasikan Skema dan Parser dengan Graphql Server

Dalam bahagian ini, kami akan menentukan corak kami, menulis fungsi parser, dan mendedahkannya ke pelayan kami.

model

Dalam folder SRC, buat folder baru bernama /skema dan buat fail bernama Schema.js di dalamnya. Tampal kod berikut:

 <code>const { gql } = require('apollo-server') const typeDefs = gql` type User {  id: Int!  username: String  email: String! } type AuthPayload {  token: String!  user: User! } type Query {  user(id: Int!): User  allUsers: [User!]!  me: User } type Mutation {  registerUser(username: String, email: String!, password: String!): AuthPayload!  login (email: String!, password: String!): AuthPayload! } ` module.exports = typeDefs</code>
Salin selepas log masuk

Di sini, kami mengimport GraphQL-Tag dari Apollo-server. Pelayan Apollo perlu membungkus corak kami dengan GQL.

Parser

Dalam folder SRC, buat folder baru bernama /resolvers dan buat fail bernama Resolver.js di dalamnya. Tampal kod berikut:

 <code>const bcrypt = require('bcryptjs') const jsonwebtoken = require('jsonwebtoken') const models = require('../models') require('dotenv').config() const resolvers = {  Query: {   async me(_, args, { user }) {    if(!user) throw new Error('You are not authenticated')    return await models.User.findByPk(user.id)   },   async user(root, { id }, { user }) {    try {     if(!user) throw new Error('You are not authenticated!')     return models.User.findByPk(id)    } catch (error) {     throw new Error(error.message)    }   },   async allUsers(root, args, { user }) {    try {     if (!user) throw new Error('You are not authenticated!')     return models.User.findAll()    } catch (error) {     throw new Error(error.message)    }   }  },  Mutation: {   async registerUser(root, { username, email, password }) {    try {     const user = await models.User.create({      username,      email,      password: await bcrypt.hash(password, 10)     })     const token = jsonwebtoken.sign(      { id: user.id, email: user.email},      process.env.JWT_SECRET,      { expiresIn: '1y' }     )     return {      token, id: user.id, username: user.username, email: user.email, message: "Authentication succesfull"     }    } catch (error) {     throw new Error(error.message)    }   },   async login(_, { email, password }) {    try {     const user = await models.User.findOne({ where: { email }})     if (!user) {      throw new Error('No user with that email')     }     const isValid = await bcrypt.compare(password, user.password)     if (!isValid) {      throw new Error('Incorrect password')     }     // return jwt     const token = jsonwebtoken.sign(      { id: user.id, email: user.email},      process.env.JWT_SECRET,      { expiresIn: '1d'}     )     return {      token, user     }   } catch (error) {    throw new Error(error.message)   }  } }, } module.exports = resolvers</code>
Salin selepas log masuk

Terdapat banyak kod, mari kita lihat apa yang berlaku di sana.

Pertama, kami mengimport model kami, bcrypt, dan jsonwebtoken, dan kemudian memulakan pembolehubah persekitaran kami.

Seterusnya ialah fungsi parser. Dalam parser pertanyaan, kami mempunyai tiga fungsi (saya, pengguna, dan penggemar):

  • Saya pertanyaan untuk mendapatkan maklumat terperinci mengenai pengguna yang sedang dilog masuk. Ia menerima objek pengguna sebagai parameter konteks. Konteks ini digunakan untuk menyediakan akses kepada pangkalan data kami, yang digunakan untuk memuatkan data pengguna melalui ID yang disediakan dalam pertanyaan.
  • Pertanyaan pengguna memperoleh maklumat terperinci pengguna berdasarkan ID pengguna. Ia menerima ID sebagai parameter konteks dan objek pengguna.
  • Pertanyaan Alluser mengembalikan butiran semua pengguna.

Jika status pengguna dilog masuk, pengguna akan menjadi objek; Jika pengguna tidak log masuk, pengguna akan menjadi batal. Kami akan membuat pengguna ini dalam mutasi kami.

Dalam parser mutasi, kami mempunyai dua fungsi (pendaftaran dan loginuser):

  • Registeruser menerima nama pengguna, e -mel, dan kata laluan pengguna dan menggunakan medan ini untuk membuat baris baru dalam pangkalan data kami. Harus diingat bahawa kami menggunakan pakej bcryptjs untuk hash kata laluan pengguna menggunakan bcrypt.hash (kata laluan, 10). jsonwebtoken.sign secara serentak menandatangani muatan yang diberikan kepada rentetan token web JSON (dalam hal ini pengguna ID dan e -mel). Akhirnya, Registeruser akan mengembalikan rentetan JWT dan profil pengguna jika berjaya; Jika ralat berlaku, mesej ralat akan dikembalikan.
  • Log masuk menerima e -mel dan kata laluan dan cek jika butiran ini sepadan dengan butiran yang disediakan. Pertama, kami periksa sama ada nilai e -mel sudah ada di dalam pangkalan data pengguna.
 <code>models.User.findOne({ where: { email }}) if (!user) { throw new Error('No user with that email') }</code>
Salin selepas log masuk

Kemudian, kami menggunakan kaedah bcrypt bcrypt.comPare untuk memeriksa sama ada kata laluan sepadan.

 <code>const isValid = await bcrypt.compare(password, user.password) if (!isValid) { throw new Error('Incorrect password') }</code>
Salin selepas log masuk

Kemudian, seperti yang kita lakukan di RegisterUser sebelum ini, kami menggunakan jsonwebtoken.sign untuk menghasilkan rentetan JWT. Log masuk mutasi pulangan token dan objek pengguna.

Sekarang mari tambahkan JWT_SECRET ke fail .Env kami.

 <code>JWT_SECRET=一个非常长的秘密</code>
Salin selepas log masuk

pelayan

Akhirnya, ia adalah pelayan! Buat server.js dalam folder root projek dan tampal yang berikut:

 <code>const { ApolloServer } = require('apollo-server') const jwt =  require('jsonwebtoken') const typeDefs = require('./schema/schema') const resolvers = require('./resolvers/resolvers') require('dotenv').config() const { JWT_SECRET, PORT } = process.env const getUser = token => { try {  if (token) {   return jwt.verify(token, JWT_SECRET)  }  return null } catch (error) {  return null } } const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => {  const token = req.get('Authorization') || ''  return { user: getUser(token.replace('Bearer', ''))} }, introspection: true, playground: true }) server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => { console.log(`? Server ready at ${url}`); });</code>
Salin selepas log masuk

Di sini kami mengimport skema, penentu, dan JWT dan memulakan pembolehubah persekitaran kami. Pertama, kami menggunakan mengesahkan untuk mengesahkan token JWT. JWT.Verify menerima kunci Token dan JWT sebagai parameter.

Seterusnya, kami membuat pelayan kami menggunakan contoh Apolloserver yang menerima typedefs dan resolver.

Kami mempunyai pelayan! Mari kita mulakan dengan menjalankan benang dev di terminal.

API ujian

Sekarang mari kita menguji API GraphQL menggunakan GraphQL Playground. Kami sepatutnya dapat mendaftar, log masuk dan melihat semua pengguna - termasuk pengguna individu - melalui ID.

Kami akan terlebih dahulu membuka aplikasi GRAPHQL Playground, atau hanya membuka localhost: // 4000 dalam penyemak imbas untuk mengaksesnya.

Mutasi untuk pengguna berdaftar

 <code>mutation { registerUser(username: "Wizzy", email: "[email protected]", password: "wizzyekpot" ){  token } }</code>
Salin selepas log masuk

Kita harus mendapat hasil seperti ini:

 <code>{ "data": {  "registerUser": {   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzAwLCJleHAiOjE2MzA3OTc5MDB9.gmeynGR9Zwng8cIJR75Qrob9bovnRQT242n6vfBt5PY"  } } }</code>
Salin selepas log masuk

Mutasi log masuk

Sekarang mari log masuk dengan butiran pengguna yang baru saja kami buat:

 <code>mutation { login(email:"[email protected]" password:"wizzyekpot"){  token } }</code>
Salin selepas log masuk

Kita harus mendapat hasil seperti ini:

 <code>{ "data": {  "login": {   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc"  } } }</code>
Salin selepas log masuk

Luar Biasa!

Pertanyaan untuk pengguna individu

Untuk menanyakan pengguna tunggal, kita perlu lulus token pengguna sebagai tajuk kebenaran. Pergi ke tab HTTP Header.

... dan tampal kandungan ini dalam:

 <code>{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" }</code>
Salin selepas log masuk

Inilah pertanyaan:

 <code>query myself{ me {  id  email  username } }</code>
Salin selepas log masuk

Kita harus mendapat hasil seperti ini:

 <code>{ "data": {  "me": {   "id": 15,   "email": "[email protected]",   "username": "Wizzy"  } } }</code>
Salin selepas log masuk

Hebat! Sekarang mari kita dapatkan pengguna dengan ID:

 <code>query singleUser{ user(id:15){  id  email  username } }</code>
Salin selepas log masuk

Berikut adalah pertanyaan untuk mendapatkan semua pengguna:

 <code>{ allUsers{  id  username  email } }</code>
Salin selepas log masuk

Meringkaskan

Pengesahan adalah salah satu tugas yang paling sukar apabila membina laman web yang memerlukan pengesahan. GraphQL membolehkan kami membina API Pengesahan Lengkap menggunakan hanya satu titik akhir. Sequelize Orm menjadikannya begitu mudah untuk mewujudkan hubungan dengan pangkalan data SQL yang kita tidak perlu bimbang tentang model kami. Ia juga perlu diperhatikan bahawa kita tidak memerlukan perpustakaan pelayan HTTP (seperti Express) tetapi menggunakan Apollo Graphql sebagai middleware. Apollo Server 2 kini membolehkan kami membuat pelayan GraphQL bebas perpustakaan kami sendiri!

Sila periksa kod sumber untuk tutorial ini di GitHub.

Atas ialah kandungan terperinci Let ' s Buat API Pengesahan Sendiri dengan NodeJs dan Graphql. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial Java
1664
14
Tutorial PHP
1267
29
Tutorial C#
1239
24
Fon Font Google Fon Fon Font Google Fon Apr 09, 2025 am 10:42 AM

Saya melihat Font Google melancarkan reka bentuk baru (tweet). Berbanding dengan reka bentuk besar yang terakhir, ini terasa lebih berulang. Saya hampir tidak dapat memberitahu perbezaannya

Cara membuat pemasa undur animasi dengan HTML, CSS dan JavaScript Cara membuat pemasa undur animasi dengan HTML, CSS dan JavaScript Apr 11, 2025 am 11:29 AM

Pernahkah anda memerlukan pemasa undur dalam projek? Untuk sesuatu seperti itu, mungkin semula jadi untuk mencapai plugin, tetapi sebenarnya lebih banyak lagi

Panduan Atribut Data HTML Panduan Atribut Data HTML Apr 11, 2025 am 11:50 AM

Semua yang anda ingin tahu mengenai atribut data dalam HTML, CSS, dan JavaScript.

Bukti konsep untuk menjadikan sass lebih cepat Bukti konsep untuk menjadikan sass lebih cepat Apr 16, 2025 am 10:38 AM

Pada permulaan projek baru, kompilasi SASS berlaku dalam sekejap mata. Ini terasa hebat, terutamanya apabila ia dipasangkan dengan BrowserSync, yang dimuat semula

Bagaimana Kami Membuat Tapak Statik yang Menjana Corak Tartan Di SVG Bagaimana Kami Membuat Tapak Statik yang Menjana Corak Tartan Di SVG Apr 09, 2025 am 11:29 AM

Tartan adalah kain berpola yang biasanya dikaitkan dengan Scotland, terutamanya kilt bergaya mereka. Di Tartanify.com, kami mengumpulkan lebih dari 5,000 Tartan

Cara Membina Komponen Vue dalam Tema WordPress Cara Membina Komponen Vue dalam Tema WordPress Apr 11, 2025 am 11:03 AM

Arahan template inline membolehkan kita membina komponen Vue yang kaya sebagai peningkatan progresif ke atas markup WordPress yang sedia ada.

Walaupun anda tidak kelihatan, kecerunan CSS menjadi lebih baik Walaupun anda tidak kelihatan, kecerunan CSS menjadi lebih baik Apr 11, 2025 am 09:16 AM

Satu perkara yang menarik perhatian saya pada senarai ciri-ciri untuk Lea Verou &#039; s conic-gradient () polyfill adalah item terakhir:

PHP adalah A-OK untuk templat PHP adalah A-OK untuk templat Apr 11, 2025 am 11:04 AM

Templat PHP sering mendapat rap buruk untuk memudahkan kod subpar - tetapi itu tidak perlu berlaku. Mari kita lihat bagaimana projek PHP dapat menguatkuasakan asas

See all articles