Skip to content
This repository was archived by the owner on Mar 19, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
],
"useGitignore": true,
"words": [
"canvaskit",
"Brickhub"
]
}
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ to the user.
| `project_title` | The title of the project | `name` attribute in the `pubspec.yaml` |
| `project_description` | The project description | `description` attribute in the `pubspec.yaml` |
| `batch_size` | How many assets will be loaded at the same time | `20` |
| `canvaskit` | If the app uses `canvaskit` mode or not | `true` |

## FAQ

Expand Down
69 changes: 50 additions & 19 deletions __brick__/web/flutter_bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,51 @@
{{=<% %>=}}{{flutter_js}}<%={{ }}=%>
{{=<% %>=}}{{flutter_build_config}}<%={{ }}=%>

const progressBar = document.querySelector('#progress-bar');
const progressText = document.querySelector('#progress-text');
const progressIndicator = document.querySelector('#progress-indicator');

async function readAssets() {
// NOTE: AssetManifest.json will be deprecated in favour of AssetManifest.bin:
// https://github.com/VeryGoodOpenSource/flutter_web_preloader/issues/28
const response = await fetch('assets/AssetManifest.json');
const manifest = await response.json();
const assets = Object.values(manifest)
.map((list) => list.map((url) => 'assets/' + url))
.reduce((arr, curr) => [...arr, ...curr], []);
// AssetManifest.bin is encoded with Flutter's Standard Message Codec.
// See: https://docs.flutter.dev/platform-integration/web/initialization
// See also: https://docs.flutter.dev/release/breaking-changes/asset-manifest-dot-json#reading-asset-manifest-information-from-dart-code-outside-of-a-flutter-app
// Keep in mind that AssetManifest.bin is an implementation detail of Flutter.
// Reading this file isn't an officially supported workflow. The contents or format of the file might change in a future Flutter release without an announcement.
const response = await fetch('assets/AssetManifest.bin');
const buffer = await response.arrayBuffer();
const view = new DataView(buffer);
let o = 0;

const readByte = () => view.getUint8(o++);
const readSize = () => {
const b = readByte();
if (b < 254) return b;
if (b === 254) { const s = view.getUint16(o, true); o += 2; return s; }
const s = view.getUint32(o, true); o += 4; return s;
};
const readString = () => {
const n = readSize();
const s = new TextDecoder().decode(new Uint8Array(buffer, o, n));
o += n;
return s;
};
const skip = () => {
const t = readByte();
if (t <= 2) return;
if (t === 7 || t === 8) { const n = readSize(); o += n; return; }
if (t === 12) { for (let i = readSize(); i > 0; i--) skip(); return; }
if (t === 13) { for (let i = readSize() * 2; i > 0; i--) skip(); }
};

// The manifest is a map; we only need its keys (the asset paths).
readByte(); // type 13 (map)
const count = readSize();
const assets = [];
for (let i = 0; i < count; i++) {
readByte(); // type 7 (string)
const path = readString();
if (!path.startsWith('packages/')) assets.push(path);
skip();
}
return assets;
}

Expand All @@ -29,15 +62,16 @@ async function beginPreloading() {
return;
}

const batchSize = {{batch_size}};
const batchSize = {{ batch_size }
};

progressIndicator.style.width = '0%';
progressText.textContent = `Loaded ${loadedAssets} of ${totalAssets} assets`;
progressIndicator.style.width = '0%';
progressText.textContent = `Loaded ${loadedAssets} of ${totalAssets} assets`;

for (let i = 0; i < assets.length; i += batchSize) {
const batch = assets.slice(i, i + batchSize);
await loadBatch(batch);
}
for (let i = 0; i < assets.length; i += batchSize) {
const batch = assets.slice(i, i + batchSize);
await loadBatch(batch);
}
}

function reportProgress() {
Expand Down Expand Up @@ -76,10 +110,7 @@ async function loadBatch(urls) {
}

_flutter.loader.load({
serviceWorkerSettings: {
serviceWorkerVersion: {{=<% %>=}}{{flutter_service_worker_version}}<%={{ }}=%>,
},
onEntrypointLoaded: async function(engineInitializer) {
onEntrypointLoaded: async function (engineInitializer) {
await Promise.all([
beginPreloading(),
engineInitializer.initializeEngine(),
Expand Down
5 changes: 0 additions & 5 deletions brick.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,3 @@ vars:
description: The number of concurrent loads that the preload will trigger.
default: 20
prompt: Pre load batch size (defaults to 20)?
canvaskit:
type: boolean
description: If the project should pre load canvaskit.
default: true
prompt: Pre load canvas kit (defaults to true)?
2 changes: 1 addition & 1 deletion hooks/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include: package:very_good_analysis/analysis_options.5.1.0.yaml
include: package:very_good_analysis/analysis_options.10.0.0.yaml
12 changes: 6 additions & 6 deletions hooks/pubspec.yaml
Comment thread
marcossevilla marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: flutter_web_preloader_hooks

environment:
sdk: ">=2.17.0 <3.0.0"
sdk: ">=3.5.0 <4.0.0"

dependencies:
mason: ^0.1.1
yaml: ^3.1.1
mason: ^0.1.2
yaml: ^3.1.2

dev_dependencies:
mocktail: ^1.0.0
test: ^1.22.2
very_good_analysis: ^5.1.0
mocktail: ^1.0.4
test: ^1.25.8
very_good_analysis: ^10.0.0
Loading