Agent Skillstekartik/sqflite › sqflite-common-ffi-web-setup

sqflite-common-ffi-web-setup

GitHub

用于在Flutter或Dart Web项目中集成sqflite数据库支持,通过运行setup命令配置WebAssembly二进制文件和IndexedDB持久化,处理跨平台数据库工厂初始化及Worker设置。

packages_web/sqflite_common_ffi_web/skills/sqflite-common-ffi-web-setup/SKILL.md tekartik/sqflite

Trigger Scenarios

需要在Web环境下使用SQLite数据库 添加sqflite_common_ffi_web依赖并执行初始化配置

Install

npx skills add tekartik/sqflite --skill sqflite-common-ffi-web-setup -g -y
More Options

Non-standard path

npx skills add https://github.com/tekartik/sqflite/tree/master/packages_web/sqflite_common_ffi_web/skills/sqflite-common-ffi-web-setup -g -y

Use without installing

npx skills use tekartik/sqflite@sqflite-common-ffi-web-setup

指定 Agent (Claude Code)

npx skills add tekartik/sqflite --skill sqflite-common-ffi-web-setup -a claude-code -g -y

安装 repo 全部 skill

npx skills add tekartik/sqflite --all -g -y

预览 repo 内 skill

npx skills add tekartik/sqflite --list

SKILL.md

Frontmatter
{
    "name": "sqflite-common-ffi-web-setup",
    "description": "Use when adding sqflite support to a web app (Flutter web or Dart web) with package:sqflite_common_ffi_web: running dart run sqflite_common_ffi_web:setup to install sqlite3.wasm and sqflite_sw.js under web\/, databaseFactoryFfiWeb, databaseFactoryFfiWebNoWebWorker, setting the global databaseFactory behind kIsWeb, database names and IndexedDB persistence, shared worker vs basic worker, importing a database with writeDatabaseBytes, limitations and troubleshooting (missing worker file, port-bound storage, deleteDatabase)."
}

sqflite_common_ffi_web: sqflite in the browser

package:sqflite_common_ffi_web implements the sqflite DatabaseFactory on the web with package:sqlite3 compiled to WebAssembly. Databases persist in IndexedDB and SQLite runs in a shared worker (one instance for all tabs). It needs two binary files served next to the app: sqlite3.wasm and the worker script sqflite_sw.js, both produced by the package setup command.

dart pub add sqflite_common_ffi_web
dart run sqflite_common_ffi_web:setup   # creates web/sqlite3.wasm and web/sqflite_sw.js
import 'package:sqflite_common/sqlite_api.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';

Future<void> main() async {
  Database db = await databaseFactoryFfiWeb.openDatabase('my_db.db');
  await db.execute('CREATE TABLE IF NOT EXISTS Test (id INTEGER PRIMARY KEY, value TEXT)');
  await db.insert('Test', {'value': 'hello'});
  print(await db.query('Test'));
  await db.close();
}

Guidelines

Dependency, binaries and import

  • Add sqflite_common_ffi_web (currently 1.1.x, Dart 3.12, platforms: web only) to dependencies. It depends on sqflite_common_ffi and sqflite_common.
  • Run dart run sqflite_common_ffi_web:setup in the project directory after adding the dependency and after every upgrade of the package or of sqlite3. It builds the shared worker with webdev (into .dart_tool/sqflite_common_ffi_web/setup/<version>/) and writes web/sqflite_sw.js plus web/sqlite3.wasm (downloaded from the sqlite3.dart GitHub releases, version pinned by the package). Options: --force (-f) rebuild, --dir <dir> output directory (default web), --verbose, --no-sqlite3-wasm (skip the wasm download), --sqlite3-wasm-url <url>, and an optional project path argument. Commit the two files or add them to .gitignore and run setup in CI; either way they must be present in the deployed site root.
  • The same setup is callable from Dart: setupSqfliteWebBinaries(options: SqfliteWebSetupOptions(...)) from package:sqflite_common_ffi_web/setup.dart (path, dir, force, verbose, sqlite3WasmUri, noSqlite3Wasm, sqlite3WasmFilename, sqfliteWebWorkerFilename). io only.
  • Import package:sqflite_common_ffi_web/sqflite_ffi_web.dart. It exports only the web factories and options (databaseFactoryFfiWeb, databaseFactoryFfiWebNoWebWorker, databaseFactoryFfiWebBasicWebWorker, createDatabaseFactoryFfiWeb, SqfliteFfiWebOptions, SqfliteFfiWebContext, sqfliteFfiWebLoadSqlite3Wasm, sqfliteFfiWebStartSharedWorker, sqliteFfiWebDebugWebWorker). The Database / DatabaseFactory types come from package:sqflite_common/sqlite_api.dart (Dart web), package:sqflite_common_ffi/sqflite_ffi.dart or package:sqflite/sqflite.dart (Flutter), so import one of them too.
  • The file compiles on io too (the getters throw UnsupportedError there), so importing it from shared code is fine as long as the factory is only touched when kIsWeb / identical(0, 0.0) is true.

Choosing the factory

  • databaseFactoryFfiWeb (tag ffi_web): SQLite runs in a SharedWorker loaded from sqflite_sw.js; all tabs of the origin share one SQLite instance, so it is cross-tab safe. When SharedWorker is unavailable (Android Chrome) it silently falls back to a dedicated Worker, which is not cross-tab safe. This is the default choice.
  • databaseFactoryFfiWebNoWebWorker: loads sqlite3.wasm in the main thread; no worker file needed, but long queries block the UI and several tabs writing the same database can corrupt it. Use for tools, demos or when workers cannot be served.
  • databaseFactoryFfiWebBasicWebWorker: testing only (forces a dedicated Worker).
  • The worker and wasm are loaded lazily on the first factory call from sqflite_sw.js / sqlite3.wasm relative to the page URL. With a non-root <base href> or another location, pass sharedWorkerUri / sqlite3WasmUri through createDatabaseFactoryFfiWeb(options: SqfliteFfiWebOptions(...)) (see sqflite-common-ffi-web-options).
  • Flutter app that already uses sqflite on mobile: keep the code, set databaseFactory = databaseFactoryFfiWeb; once at startup when kIsWeb, before the first openDatabase. The global openDatabase() then works on all platforms. Use sqflite_common_ffi (databaseFactoryFfi) for the desktop counterpart.

Paths and persistence

  • getDatabasesPath() returns / and relative paths are used as is: a database name such as my_db.db is a key in the virtual file system, not a file. Do not build paths with path_provider on the web.
  • Storage is an IndexedDB database named sqflite_databases (override with SqfliteFfiWebOptions.indexedDbName) holding every sqflite database of the origin. IndexedDB is per origin including the port: localhost:8080 and localhost:8081 are different stores, so always debug on the same port. There is no OPFS backend.
  • inMemoryDatabasePath opens a private in-memory SQLite database inside the worker (nothing stored).
  • To import a bundled database (asset or download), write its bytes with factory.writeDatabaseBytes(path, bytes) then openDatabase(path); readDatabaseBytes(path) exports it. databaseExists, deleteDatabase work on the virtual file system.
  • sqfliteFfiInit() from sqflite_common_ffi is a no-op on the web; calling it in shared code is harmless.

Limitations

  • Experimental: slower than native, larger message overhead (each call goes through postMessage), not fully tested.
  • dart2wasm (flutter build web --wasm) is supported since 1.2.0 with sqflite_common 2.5.13 or later; with older versions deleteDatabase and databaseExists silently fail when the app is compiled with dart2wasm.
  • Basic Worker fallback (Android Chrome) is not cross-tab safe.
  • One connection per database: OpenDatabaseOptions(singleInstance: false) throws an ArgumentError for a persistent database. Every connection of a factory runs in the same wasm instance on the same virtual file system, which has no locking between connections, so a second connection to the same file could corrupt it. Keep the default singleInstance: true (the same Database is returned for the same path); only inMemoryDatabasePath can be opened several times.
  • Only one worker script name per site: the shared worker is keyed by its URL, so after upgrading the package all tabs must reload. To force a reload change the worker file name (see options skill, sw_js_file).

Examples

Flutter app: web + mobile + desktop

import 'dart:io' show Platform;

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/widgets.dart';
// sqflite_ffi.dart exports the whole sqflite_common API (openDatabase,
// databaseFactory...); package:sqflite/sqflite.dart would be redundant.
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (kIsWeb) {
    databaseFactory = databaseFactoryFfiWeb;
  } else if (Platform.isWindows || Platform.isLinux) {
    sqfliteFfiInit();
    databaseFactory = databaseFactoryFfi;
  }
  // Global openDatabase() now works everywhere; on the web the path is a name.
  var db = await openDatabase(
    'app.db',
    version: 1,
    onCreate: (db, _) => db.execute(
      'CREATE TABLE Note (id INTEGER PRIMARY KEY, text TEXT)',
    ),
  );
  await db.insert('Note', {'text': 'hello'});
  runApp(const SizedBox());
}

Dart web app (no Flutter)

import 'package:sqflite_common/sqlite_api.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';

Future<void> main() async {
  var factory = databaseFactoryFfiWeb;
  var db = await factory.openDatabase(
    'counter.db',
    options: OpenDatabaseOptions(
      version: 1,
      onCreate: (db, _) =>
          db.execute('CREATE TABLE Counter (id INTEGER PRIMARY KEY, value INTEGER)'),
    ),
  );
  await db.rawInsert(
    'INSERT INTO Counter(id, value) VALUES (1, 0) ON CONFLICT(id) DO UPDATE SET value = value + 1',
  );
  print(await db.query('Counter'));
  await db.close();
}

Importing an asset database on Flutter web

import 'package:flutter/services.dart' show rootBundle;
import 'package:sqflite/sqflite.dart';

Future<Database> openBundledDatabase() async {
  const path = 'bundled.db';
  if (!await databaseFactory.databaseExists(path)) {
    final data = await rootBundle.load('assets/bundled.db');
    final bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    await databaseFactory.writeDatabaseBytes(path, bytes);
  }
  return openDatabase(path, readOnly: true);
}

Main-thread factory for a small tool page

import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';

Future<String> sqliteVersion() async {
  // Only sqlite3.wasm is required, no sqflite_sw.js.
  var db = await databaseFactoryFfiWebNoWebWorker.openDatabase('tool.db');
  try {
    return (await db.rawQuery('SELECT sqlite_version()')).first.values.first
        as String;
  } finally {
    await db.close();
  }
}

Common mistakes

  • Forgetting dart run sqflite_common_ffi_web:setup: the first call fails and the console prints "An error occurred while initializing the web worker ... failure to find the worker javascript file at sqflite_sw.js".
  • Serving the app from a sub path without adjusting sharedWorkerUri / sqlite3WasmUri, or a server that does not serve .wasm as application/wasm.
  • Upgrading sqflite_common_ffi_web or sqlite3 without re-running setup (--force if the files look up to date but the wasm version changed).
  • Using getDatabasesPath() + join or path_provider on the web; use a plain name.
  • Debugging on changing ports and "losing" the database.
  • Passing singleInstance: false in shared code (for example for a background task or a second controller): it throws on the web; share the single instance instead.
  • Setting databaseFactory = databaseFactoryFfiWeb on io (throws UnsupportedError): guard with kIsWeb.
  • Importing only sqflite_ffi_web.dart and expecting Database or OpenDatabaseOptions to be defined; add package:sqflite_common/sqlite_api.dart (or sqflite).

Version History

  • aaabf90 Current 2026-09-22 03:38

Same Skill Collection

packages/sqflite_common_ffi_async_test/skills/sqflite-common-ffi-async-test-suite/SKILL.md
packages/sqflite_common_ffi_async/skills/sqflite-common-ffi-async-factory/SKILL.md
sqflite_android/skills/sqflite-android-setup/SKILL.md
sqflite_common_ffi/skills/sqflite-common-ffi-testing/SKILL.md
packages_flutter/sqflite_ffi/skills/sqflite-ffi-flutter/SKILL.md
packages_web/sqflite_common_ffi_web_test/skills/sqflite-common-ffi-web-test-suite/SKILL.md
packages_web/sqflite_common_ffi_web/skills/sqflite-common-ffi-web-options/SKILL.md
sqflite_common_ffi/skills/sqflite-common-ffi-desktop/SKILL.md
sqflite_common_test/skills/sqflite-common-test-suite/SKILL.md
sqflite_common/skills/sqflite-common-api/SKILL.md
sqflite_darwin/skills/sqflite-darwin-setup/SKILL.md
sqflite_platform_interface/skills/sqflite-platform-interface-implementers/SKILL.md
sqflite/skills/sqflite-crud-and-transactions/SKILL.md
sqflite/skills/sqflite-open-database/SKILL.md
sqflite/skills/sqflite-testing-and-platforms/SKILL.md

Metadata

Files
0
Version
aaabf90
Hash
a7aa29b6
Indexed
2026-09-22 03:38

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-22 09:59
浙ICP备14020137号-1