cari
Rumahhujung hadapan webtutorial js[Laman Web Peribadi] Cara Mengintegrasikan Pangkalan Data Notion dalam Seterusnya

Untuk menyepadukan pangkalan data Notion ke dalam projek Next.js, anda boleh menggunakan Notion sebagai sistem pengurusan kandungan (CMS) dan memaparkan kandungannya di tapak web anda. Di bawah ialah panduan langkah demi langkah yang mudah untuk membantu anda menyepadukan pangkalan data Notion ke dalam Next.js.

Persediaan Asas

Dapatkan Kunci API Notion dan ID Pangkalan Data

  1. Dapatkan Kunci API Notion: Pergi ke Portal Pembangun Notion dan buat penyepaduan baharu. Setelah dibuat, anda akan menerima kunci API.
  2. Dapatkan ID Pangkalan Data: Navigasi ke pangkalan data Notion yang anda mahu integrasikan, dan salin URL halaman pangkalan data. ID pangkalan data ialah rentetan aksara antara https://www.notion.so/ dan ?v= dalam URL.

[Personal Website] How to Integrate Notion Database in Next

还不清楚的可以看上篇文章:【01.【个人网站】如何使用Notion作为数据库倨数据库倨进行

Menggunakan SDK Rasmi

Langkah 1: Pasang Ketergantungan

Pertama, anda perlu memasang SDK rasmi Notion, @notionhq/client, untuk berkomunikasi dengan API Notion. Anda boleh memasangnya menggunakan npm atau yarn:


npm install @notionhq/client
# or
yarn add @notionhq/client

Langkah 2: Sediakan Klien Notion

Buat fail lib/notion.js dalam direktori akar projek Next.js anda dan konfigurasikan klien Notion seperti berikut:


// lib/notion.js
import { Client } from '@notionhq/client';

const notion = new Client({
  auth: process.env.NOTION_API_KEY,
});

export const getDatabase = async (databaseId) => {
  const response = await notion.databases.query({ database_id: databaseId });
  return response.results;
};

Pastikan menyimpan kunci API Notion anda dalam pembolehubah persekitaran NOTION_API_KEY.(.env.local)


NOTION_API_KEY=your_secret_api_key

Langkah 3: Ambil Kandungan Pangkalan Data

Dalam halaman Next.js anda, anda boleh menggunakan getStaticProps atau getServerSideProps untuk mengambil kandungan daripada pangkalan data Notion.


// pages/index.js
import { getDatabase } from '../lib/notion';

export const getStaticProps = async () => {
  const databaseId = process.env.NOTION_DATABASE_ID;
  const posts = await getDatabase(databaseId);

  return {
    props: {
      posts,
    },
    revalidate: 1, // ISR (Incremental Static Regeneration)
  };
};

export default function Home({ posts }) {
  return (
    <div>
      <h1 id="My-Notion-Blog">My Notion Blog</h1>
      <ul>
        {posts.map((post) => (
          <li key="{post.id}">
            {post.properties.Name.title[0].plain_text}
          </li>
        ))}
      </ul>
    </div>
  );
}

Pastikan anda mempunyai ID pangkalan data Notion anda disimpan dalam NOTION_DATABASE_ID sebagai pembolehubah persekitaran.


NOTION_DATABASE_ID=your_database_id

Langkah 4: Penerapan dan Pengesahan

Akhir sekali, gunakan projek Next.js anda ke Vercel atau platform lain dan sahkan bahawa anda berjaya mengambil dan memaparkan data daripada pangkalan data Notion.

Petua Tambahan

    Anda boleh memaparkan sifat halaman Notion yang berbeza (seperti Nama, Teg, Tarikh, dll.) pada halaman anda.
  • Pertimbangkan untuk menggunakan getServerSideProps untuk mengambil data pada setiap permintaan atau gunakan getStaticProps dengan ISR (Incremental Static Regeneration) untuk mengoptimumkan prestasi.
Dengan mengikut langkah ini, anda boleh berjaya menyepadukan pangkalan data Notion ke dalam projek Next.js anda dan menggunakannya untuk mengurus serta memaparkan kandungan.

Menggunakan Notion API dengan URL Berbalut

Akhir sekali, saya akhirnya menggunakan kaedah ini untuk kemudahan apabila menyepadukan dengan komponen react-notion-x.

Pastikan anda menambah ID Pangkalan Data Notion dan Kunci API Notion anda pada fail .env.local:


NOTION_DATABASE_ID=your_database_id
NOTION_API_KEY=your_secret_api_key
Langkah 1: Pasang kebergantungan yang diperlukan

Mula-mula, pasang kebergantungan yang diperlukan seperti notion-types, notion-utils dan perlu mengendalikan permintaan kepada Notion API.


npm install notion-types notion-utils got p-map

Langkah 2: Buat fail untuk merangkum interaksi Notion API

Dalam projek Next.js anda, buat fail, contohnya, lib/NotionAPI.ts, yang akan merangkum interaksi dengan API Notion. Fail ini akan mengandungi kaedah untuk memanggil titik akhir Notion API untuk mengambil data daripada halaman dan koleksi.


// lib/NotionAPI.ts
import * as notion from "notion-types";
import got, { OptionsOfJSONResponseBody } from "got";
import {
  getBlockCollectionId,
  getPageContentBlockIds,
  parsePageId,
  uuidToId,
} from "notion-utils";
import pMap from "p-map";

// 定义权限记录接口
export interface SignedUrlRequest {
  permissionRecord: PermissionRecord;
  url: string;
}

export interface PermissionRecord {
  table: string;
  id: notion.ID;
}

export interface SignedUrlResponse {
  signedUrls: string[];
}

// 定义NotionAPI类
export class NotionAPI {
  private readonly _apiBaseUrl: string;
  private readonly _authToken?: string;
  private readonly _activeUser?: string;
  private readonly _userTimeZone: string;

  constructor({
    apiBaseUrl = "<https:>",
    authToken,
    activeUser,
    userTimeZone = "America/New_York",
  }: {
    apiBaseUrl?: string;
    authToken?: string;
    userLocale?: string;
    userTimeZone?: string;
    activeUser?: string;
  } = {}) {
    this._apiBaseUrl = apiBaseUrl;
    this._authToken = authToken;
    this._activeUser = activeUser;
    this._userTimeZone = userTimeZone;
  }

  // 获取页面内容
  public async getPage(
    pageId: string,
    {
      concurrency = 3,
      fetchMissingBlocks = true,
      fetchCollections = true,
      signFileUrls = true,
      chunkLimit = 100,
      chunkNumber = 0,
      gotOptions,
    }: {
      concurrency?: number;
      fetchMissingBlocks?: boolean;
      fetchCollections?: boolean;
      signFileUrls?: boolean;
      chunkLimit?: number;
      chunkNumber?: number;
      gotOptions?: OptionsOfJSONResponseBody;
    } = {}
  ): Promise<notion.extendedrecordmap> {
    const page = await this.getPageRaw(pageId, {
      chunkLimit,
      chunkNumber,
      gotOptions,
    });

    const recordMap = page?.recordMap as notion.ExtendedRecordMap;

    if (!recordMap?.block) {
      throw new Error(`Notion page not found "${uuidToId(pageId)}"`);
    }

    recordMap.collection = recordMap.collection ?? {};
    recordMap.collection_view = recordMap.collection_view ?? {};
    recordMap.notion_user = recordMap.notion_user ?? {};
    recordMap.collection_query = {};
    recordMap.signed_urls = {};

    if (fetchMissingBlocks) {
      while (true) {
        const pendingBlockIds = getPageContentBlockIds(recordMap).filter(
          (id) => !recordMap.block[id]
        );

        if (!pendingBlockIds.length) {
          break;
        }

        const newBlocks = await this.getBlocks(
          pendingBlockIds,
          gotOptions
        ).then((res) => res.recordMap.block);

        recordMap.block = { ...recordMap.block, ...newBlocks };
      }
    }

    const contentBlockIds = getPageContentBlockIds(recordMap);

    if (fetchCollections) {
      const allCollectionInstances: Array = contentBlockIds.flatMap((blockId) => {
        const block = recordMap.block[blockId].value;
        const collectionId =
          block &&
          (block.type === "collection_view" ||
            block.type === "collection_view_page") &&
          getBlockCollectionId(block, recordMap);

        if (collectionId) {
          return block.view_ids?.map((collectionViewId) => ({
            collectionId,
            collectionViewId,
          }));
        } else {
          return [];
        }
      });

      await pMap(
        allCollectionInstances,
        async (collectionInstance) => {
          const { collectionId, collectionViewId } = collectionInstance;
          const collectionView =
            recordMap.collection_view[collectionViewId]?.value;

          try {
            const collectionData = await this.getCollectionData(
              collectionId,
              collectionViewId,
              collectionView,
              {
                gotOptions,
              }
            );

            recordMap.block = {
              ...recordMap.block,
              ...collectionData.recordMap.block,
            };

            recordMap.collection = {
              ...recordMap.collection,
              ...collectionData.recordMap.collection,
            };

            recordMap.collection_view = {
              ...recordMap.collection_view,
              ...collectionData.recordMap.collection_view,
            };

            recordMap.notion_user = {
              ...recordMap.notion_user,
              ...collectionData.recordMap.notion_user,
            };

            recordMap.collection_query![collectionId] = {
              ...recordMap.collection_query![collectionId],
              [collectionViewId]: (collectionData.result as any)
                ?.reducerResults,
            };
          } catch (err: any) {
            console.warn(
              "NotionAPI collectionQuery error",
              pageId,
              err.message
            );
          }
        },
        {
          concurrency,
        }
      );
    }

    if (signFileUrls) {
      await this.addSignedUrls({ recordMap, contentBlockIds, gotOptions });
    }

    return recordMap;
  }

  public async addSignedUrls({
    recordMap,
    contentBlockIds,
    gotOptions = {},
  }: {
    recordMap: notion.ExtendedRecordMap;
    contentBlockIds?: string[];
    gotOptions?: OptionsOfJSONResponseBody;
  }) {
    recordMap.signed_urls = {};

    if (!contentBlockIds) {
      contentBlockIds = getPageContentBlockIds(recordMap);
    }

    const allFileInstances = contentBlockIds.flatMap((blockId) => {
      const block = recordMap.block[blockId]?.value;

      if (
        block &&
        (block.type === "pdf" ||
          block.type === "audio" ||
          (block.type === "image" && block.file_ids?.length) ||
          block.type === "video" ||
          block.type === "file" ||
          block.type === "page")
      ) {
        const source =
          block.type === "page"
            ? block.format?.page_cover
            : block.properties?.source?.[0]?.[0];

        if (source) {
          if (!source.includes("secure.notion-static.com")) {
            return [];
          }

          return {
            permissionRecord: {
              table: "block",
              id: block.id,
            },
            url: source,
          };
        }
      }

      return [];
    });

    if (allFileInstances.length > 0) {
      try {
        const { signedUrls } = await this.getSignedFileUrls(
          allFileInstances,
          gotOptions
        );

        if (signedUrls.length === allFileInstances.length) {
          for (let i = 0; i  {
    const parsedPageId = parsePageId(pageId);

    if (!parsedPageId) {
      throw new Error(`invalid notion pageId "${pageId}"`);
    }

    const body = {
      pageId: parsedPageId,
      limit: chunkLimit,
      chunkNumber: chunkNumber,
      cursor: { stack: [] },
      verticalColumns: false,
    };

    return this.fetch<notion.pagechunk>({
      endpoint: "loadPageChunk",
      body,
      gotOptions,
    });
  }

  public async getCollectionData(
    collectionId: string,
    collectionViewId: string,
    collectionView?: any,
    {
      limit = 9999,
      searchQuery = "",
      userTimeZone = this._userTimeZone,
      loadContentCover = true,
      gotOptions,
    }: {
      limit?: number;
      searchQuery?: string;
      userTimeZone?: string;
      loadContentCover?: boolean;
      gotOptions?: OptionsOfJSONResponseBody;
    } = {}
  ) {
    const type = collectionView?.type;

    const isBoardType = type === "board";
    const groupBy = isBoardType
      ? collectionView?.format?.board_columns_by
      : collectionView?.format?.collection_group_by;

    let filters = [];
    if (collectionView?.format?.property_filters) {
      filters = collectionView.format?.property_filters.map(
        (filterObj

: any) => ({
          property: filterObj?.property,
          filter: {
            operator: "and",
            filters: filterObj?.filter?.filters,
          },
        })
      );
    }

    const body = {
      collection: {
        id: collectionId,
      },
      collectionView: {
        id: collectionViewId,
      },
      loader: {
        type: "reducer",
        reducers: {
          collection_group_results: {
            type: "results",
            limit,
            loadContentCover,
          },
        },
        userTimeZone,
        limit,
        loadContentCover,
        searchQuery,
        userLocale: "en",
        ...(filters.length > 0 ? { filters } : {}),
        ...(groupBy
          ? {
              groupBy,
            }
          : {}),
      },
    };

    return this.fetch<notion.collectioninstance>({
      endpoint: "queryCollection",
      body,
      gotOptions,
    });
  }

  private async fetch<r>({
    endpoint,
    body,
    gotOptions,
  }: {
    endpoint: string;
    body: unknown;
    gotOptions?: OptionsOfJSONResponseBody;
  }) {
    const url = `${this._apiBaseUrl}/${endpoint}`;
    const json = true;
    const method = "POST";

    const headers: Record<string string> = {
      "Content-Type": "application/json",
    };

    if (this._authToken) {
      headers.cookie = `token_v2=${this._authToken}`;
    }

    if (this._activeUser) {
      headers["x-notion-active-user-header"] = this._activeUser;
    }

    try {
      const res = await got.post(url, {
        ...gotOptions,
        json,
        method,
        body,
        headers,
      });

      return res.body as R;
    } catch (err) {
      console.error(`NotionAPI error: ${err.message}`);
      throw err;
    }
  }

  private async getSignedFileUrls(
    urls: SignedUrlRequest[],
    gotOptions?: OptionsOfJSONResponseBody
  ): Promise<signedurlresponse> {
    return this.fetch<signedurlresponse>({
      endpoint: "getSignedFileUrls",
      body: { urls },
      gotOptions,
    });
  }

  private async getBlocks(
    blockIds: string[],
    gotOptions?: OptionsOfJSONResponseBody
  ): Promise<notion.pagechunk> {
    return this.fetch<notion.pagechunk>({
      endpoint: "syncRecordValues",
      body: {
        requests: blockIds.map((blockId) => ({
          id: blockId,
          table: "block",
          version: -1,
        })),
      },
      gotOptions,
    });
  }
}

</notion.pagechunk></notion.pagechunk></signedurlresponse></signedurlresponse></string></r></notion.collectioninstance></notion.pagechunk></notion.extendedrecordmap></https:>

Langkah 3: Gunakan Encapsulated API dalam Next.js Pages

Untuk mengambil kandungan pangkalan data Notion dalam halaman Next.js anda, anda boleh menggunakan kelas NotionAPI terkapsul dan menghantar data yang diambil kepada komponen reaksi-notion-x untuk pemaparan.


// pages/[pageId].tsx
import { GetServerSideProps } from 'next';
import { NotionAPI } from '../lib/NotionAPI';
import { NotionRenderer } from 'react-notion-x';
import 'react-notion-x/src/styles.css';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const { pageId } = context.params;
  const notion = new NotionAPI();
  const recordMap = await notion.getPage(pageId as string);

  return {
    props: {
      recordMap,
    },
  };
};

const NotionPage = ({ recordMap }) => {
  return <notionrenderer recordmap="{recordMap}" fullpage="{true}" darkmode="{false}"></notionrenderer>;
};

export default NotionPage;

Langkah 4: Konfigurasikan Penghalaan dalam Next.js

Untuk memastikan bahawa fail [pageId].tsx boleh memaparkan halaman Notion yang berbeza secara dinamik, anda perlu menyediakan penghalaan dinamik dalam Next.js. Ini akan membolehkan anda memadankan parameter pageId dan mengambil kandungan halaman Notion yang sepadan.

Berikut ialah cara anda boleh mengkonfigurasi laluan dinamik:

  1. Buat Fail Laluan Dinamik dalam direktori halaman:
Dalam direktori halaman anda, buat fail baharu bernama [pageId].tsx:


pages/[pageId].tsx
  1. Laksanakan Perenderan Halaman Dinamik:
Dalam fail [pageId].tsx, ambil kandungan Notion berdasarkan pageId daripada URL dan jadikannya secara dinamik.

Contoh kod:


import { GetStaticProps, GetStaticPaths } from 'next';
import { NotionRenderer } from 'react-notion-x';
import { getNotionPageData } from '../lib/NotionAPI';
import 'react-notion-x/src/styles.css';

export default function NotionPage({ pageData }) {
  return (
    <div>
      <notionrenderer recordmap="{pageData}" fullpage="{true}" darkmode="{false}"></notionrenderer>
    </div>
  );
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const { pageId } = params!;
  const pageData = await getNotionPageData(pageId as string);

  return {
    props: {
      pageData,
    },
    revalidate: 10, // Revalidate content every 10 seconds (ISR)
  };
};

export const getStaticPaths: GetStaticPaths = async () => {
  return {
    paths: [], // We’ll use fallback to handle dynamic routes
    fallback: 'blocking', // Generate pages on the fly if not pre-rendered
  };
};
  1. Explanation:
  2. getStaticPaths: Since your content is dynamic, we return an empty array for paths and set fallback: 'blocking' to generate pages on demand.
  3. getStaticProps: Fetches the Notion page content based on the pageId passed in the URL.

Summary

By following the steps above, you can now encapsulate Notion API requests and render Notion pages dynamically in your Next.js project using react-notion-x. This setup allows you to efficiently integrate Notion as a CMS while ensuring scalability and maintainability in your Next.js application.

Atas ialah kandungan terperinci [Laman Web Peribadi] Cara Mengintegrasikan Pangkalan Data Notion dalam Seterusnya. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
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
Adakah JavaScript ditulis dalam C? Memeriksa buktiAdakah JavaScript ditulis dalam C? Memeriksa buktiApr 25, 2025 am 12:15 AM

Ya, teras enjin JavaScript ditulis dalam C. 1) Bahasa C menyediakan prestasi yang efisien dan kawalan asas, yang sesuai untuk pembangunan enjin JavaScript. 2) Mengambil enjin V8 sebagai contoh, terasnya ditulis dalam C, menggabungkan kecekapan dan ciri-ciri berorientasikan objek C. 3) Prinsip kerja enjin JavaScript termasuk parsing, penyusun dan pelaksanaan, dan bahasa C memainkan peranan penting dalam proses ini.

Peranan JavaScript: Membuat Web Interaktif dan DinamikPeranan JavaScript: Membuat Web Interaktif dan DinamikApr 24, 2025 am 12:12 AM

JavaScript adalah di tengah -tengah laman web moden kerana ia meningkatkan interaktiviti dan dinamik laman web. 1) Ia membolehkan untuk menukar kandungan tanpa menyegarkan halaman, 2) memanipulasi laman web melalui Domapi, 3) menyokong kesan interaktif kompleks seperti animasi dan drag-and-drop, 4) mengoptimumkan prestasi dan amalan terbaik untuk meningkatkan pengalaman pengguna.

C dan JavaScript: Sambungan dijelaskanC dan JavaScript: Sambungan dijelaskanApr 23, 2025 am 12:07 AM

C dan JavaScript mencapai interoperabilitas melalui webassembly. 1) Kod C disusun ke dalam modul WebAssembly dan diperkenalkan ke dalam persekitaran JavaScript untuk meningkatkan kuasa pengkomputeran. 2) Dalam pembangunan permainan, C mengendalikan enjin fizik dan rendering grafik, dan JavaScript bertanggungjawab untuk logik permainan dan antara muka pengguna.

Dari laman web ke aplikasi: Aplikasi pelbagai JavaScriptDari laman web ke aplikasi: Aplikasi pelbagai JavaScriptApr 22, 2025 am 12:02 AM

JavaScript digunakan secara meluas di laman web, aplikasi mudah alih, aplikasi desktop dan pengaturcaraan sisi pelayan. 1) Dalam pembangunan laman web, JavaScript mengendalikan DOM bersama -sama dengan HTML dan CSS untuk mencapai kesan dinamik dan menyokong rangka kerja seperti JQuery dan React. 2) Melalui reaktnatif dan ionik, JavaScript digunakan untuk membangunkan aplikasi mudah alih rentas platform. 3) Rangka kerja elektron membolehkan JavaScript membina aplikasi desktop. 4) Node.js membolehkan JavaScript berjalan di sisi pelayan dan menyokong permintaan serentak yang tinggi.

Python vs JavaScript: Gunakan Kes dan Aplikasi MembandingkanPython vs JavaScript: Gunakan Kes dan Aplikasi MembandingkanApr 21, 2025 am 12:01 AM

Python lebih sesuai untuk sains data dan automasi, manakala JavaScript lebih sesuai untuk pembangunan front-end dan penuh. 1. Python berfungsi dengan baik dalam sains data dan pembelajaran mesin, menggunakan perpustakaan seperti numpy dan panda untuk pemprosesan data dan pemodelan. 2. Python adalah ringkas dan cekap dalam automasi dan skrip. 3. JavaScript sangat diperlukan dalam pembangunan front-end dan digunakan untuk membina laman web dinamik dan aplikasi satu halaman. 4. JavaScript memainkan peranan dalam pembangunan back-end melalui Node.js dan menyokong pembangunan stack penuh.

Peranan C/C dalam JavaScript Jurubah dan PenyusunPeranan C/C dalam JavaScript Jurubah dan PenyusunApr 20, 2025 am 12:01 AM

C dan C memainkan peranan penting dalam enjin JavaScript, terutamanya digunakan untuk melaksanakan jurubahasa dan penyusun JIT. 1) C digunakan untuk menghuraikan kod sumber JavaScript dan menghasilkan pokok sintaks abstrak. 2) C bertanggungjawab untuk menjana dan melaksanakan bytecode. 3) C melaksanakan pengkompil JIT, mengoptimumkan dan menyusun kod hot-spot semasa runtime, dan dengan ketara meningkatkan kecekapan pelaksanaan JavaScript.

JavaScript in Action: Contoh dan projek dunia nyataJavaScript in Action: Contoh dan projek dunia nyataApr 19, 2025 am 12:13 AM

Aplikasi JavaScript di dunia nyata termasuk pembangunan depan dan back-end. 1) Memaparkan aplikasi front-end dengan membina aplikasi senarai TODO, yang melibatkan operasi DOM dan pemprosesan acara. 2) Membina Restfulapi melalui Node.js dan menyatakan untuk menunjukkan aplikasi back-end.

JavaScript dan Web: Fungsi teras dan kes penggunaanJavaScript dan Web: Fungsi teras dan kes penggunaanApr 18, 2025 am 12:19 AM

Penggunaan utama JavaScript dalam pembangunan web termasuk interaksi klien, pengesahan bentuk dan komunikasi tak segerak. 1) kemas kini kandungan dinamik dan interaksi pengguna melalui operasi DOM; 2) pengesahan pelanggan dijalankan sebelum pengguna mengemukakan data untuk meningkatkan pengalaman pengguna; 3) Komunikasi yang tidak bersesuaian dengan pelayan dicapai melalui teknologi Ajax.

See all articles

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

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

Versi Mac WebStorm

Versi Mac WebStorm

Alat pembangunan JavaScript yang berguna

SublimeText3 Linux versi baharu

SublimeText3 Linux versi baharu

SublimeText3 Linux versi terkini

MinGW - GNU Minimalis untuk Windows

MinGW - GNU Minimalis untuk Windows

Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.