Skip to content

Commit

Permalink
adding 'astro' bundler plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
getify committed Aug 9, 2024
1 parent 776aef7 commit 439a7e9
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 14 deletions.
41 changes: 35 additions & 6 deletions BUNDLERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

This project has non-ESM dependencies, which unfortunately cannot be *bundled* in with your other app code. Modern bundlers unfortunately don't out-of-the-box support configurations that can handle such a situation.

As such, this project provides plugins for Vite and Webpack, to take care of the various steps needed to get these non-ESM dependencies into an otherwise bundled web app built by those tools.
As such, this project provides plugins for Astro, Vite, and Webpack, to take care of the various steps needed to get these non-ESM dependencies into an otherwise bundled web app built by those tools.

## Bundler Plugins

The plugins for Vite and Webpack are included in the `bundler-plugins/` directory. They should handle all necessary steps to load the dependencies.
The plugins for Astro, Vite, and Webpack are included in the `bundler-plugins/` directory. They should handle all necessary steps to load the dependencies.

**Note:** You should not need to manually copy any files out of the `dist/bundlers/` directory, as the plugins access the `qr-data-sync` dependency (in `node_modules`) directly to pull the files needed. But for reference, the files these plugins access are:

Expand All @@ -22,9 +22,38 @@ The plugins for Vite and Webpack are included in the `bundler-plugins/` director

- `dist/auto/external/qrcode.js`

### Astro Plugin (aka Integration)

If using Astro 4+, it's strongly suggested to import this library's Astro-plugin to manage the loading of its non-ESM dependencies. Add something like the following to your `astro.config.mjs` file:

```js
import { defineConfig } from "astro/config";

import QRDS from "@lo-fi/qr-data-sync/bundlers/astro";

export default defineConfig({
// ..

integrations: [ QRDS(), ],

vite: {
plugins: [
// pulls in some necessary bits of QRDS's vite plugin
QRDS.vite(),
],
},

// ..
});
```

In all cases, it copies the `dist/bundlers/qrds-external-bundle.js` file into the `public/` directory of your project root, as well as the `dist/` directory when running a build. It also injects an inline `<script>` element into the `<head>` of all generated pages, which dynamically loads the `/qrds-external-bundle.js` script file (which has all the external dependencies needed).

**Note:** At present, this plugin is not configurable in any way (i.e., calling `QRDS()` above with no arguments). If something about its behavior is not compatible with your Astro project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `qr-data-sync/bundler-plugins/astro.mjs` plugin and make necessary changes.

### Vite Plugin

If using Vite 5+, it's strongly suggested to import this library's Vite-plugin to manage the loading of its non-ESM dependencies. Add something like the following to your `vite.config.js` file:
If directly using Vite 5+, it's strongly suggested to import this library's Vite-plugin to manage the loading of its non-ESM dependencies. Add something like the following to your `vite.config.js` file:

```js
import { defineConfig } from "vite";
Expand All @@ -45,7 +74,7 @@ This plugin works for the `vite dev` (dev-server), `vite preview` (also dev-serv

#### SSR Breakage

An unfortunate gotcha of tools that wrap Vite (e.g., Astro, Nuxt, etc) and do SSR (server-side rendering) is that they *break* a key assumption/behavior of this module's Vite plugin: the HTML injection of `<script src="/qrds-external-bundle.js"></script>`.
An unfortunate gotcha of some tools that wrap Vite (e.g., Nuxt, etc) and do SSR (server-side rendering) is that they *break* a key assumption/behavior of this module's Vite plugin: the HTML injection of `<script src="/qrds-external-bundle.js"></script>`.

As such, you'll likely need to manually add that `<script>` tag to your HTML pages/templates. The Vite plugin still copies that file into the `public/` folder for you, so it should load once the tag is added to your HTML.

Expand Down Expand Up @@ -86,7 +115,7 @@ This plugin copies the `dist/bundlers/qrds-external-bundle.js` file into the bui
To import and use **qr-data-sync** in a *bundled* browser app:

```js
import { todo } from "qr-data-sync";
import { send, receive } from "qr-data-sync";
```

When `import`ed like this, both Vite and Webpack should (via these plugins) properly find and bundle the `dist/bundlers/qrds.js` ESM library module with the rest of your app code, hopefully without any further steps necessary.
When `import`ed like this, Astro, Vite, and Webpack should (via these plugins) properly find and bundle the `dist/bundlers/qrds.mjs` ESM library module with the rest of your app code, hopefully without any further steps necessary.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The [**@lo-fi/qr-data-sync** npm package](https://npmjs.com/package/@lo-fi/qr-da

If you obtain this library via git instead of npm, you'll need to [build `dist/` manually](#re-building-dist) before deployment.

* **USING A WEB BUNDLER?** (Vite, Webpack, etc) Use the `dist/bundlers/*` files and see [Bundler Deployment](BUNDLERS.md) for instructions.
* **USING A WEB BUNDLER?** (Astro, Vite, Webpack, etc) Use the `dist/bundlers/*` files and see [Bundler Deployment](BUNDLERS.md) for instructions.

* Otherwise, use the `dist/auto/*` files and see [Non-Bundler Deployment](NON-BUNDLERS.md) for instructions.

Expand All @@ -36,7 +36,7 @@ If you obtain this library via git instead of npm, you'll need to [build `dist/`
To generate an "animated" QR code (cycle of frames) that *sends* data, use `send()`:

```js
import { send } from "...";
import { send } from "..";

var sendData = { /* ... */ };
var qrCodeIDOrElement = /* ... */;
Expand Down Expand Up @@ -89,7 +89,7 @@ Optional configuration can be passed in as properties of an object, as the third
* `signal` (AbortSignal): an [`AbortController.signal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) instance to stop/cancel the sending "animation".

```js
import { send } from "...";
import { send } from "..";

var cancelToken = new AbortController();
var sendStarted = await send( /* .. */, { signal: cancelToken.signal });
Expand Down Expand Up @@ -117,7 +117,7 @@ Optional configuration can be passed in as properties of an object, as the third
To scan an "animated" QR code (cycle of frames) that *receives* data, use `receive()`:

```js
import { receive } from "...";
import { receive } from "..";

var videoIDorElement = /* ... */;
var receiveOptions = { /* ... */ };
Expand Down Expand Up @@ -159,7 +159,7 @@ Optional configuration can be passed in as properties of an object, as the secon
* `signal` (AbortSignal): an [`AbortController.signal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) instance to stop/cancel the receive scanning.

```js
import { receive } from "...";
import { receive } from "..";

var cancelToken = new AbortController();
var receiveResult = await receive( /* .. */, { signal: cancelToken.signal });
Expand Down
62 changes: 62 additions & 0 deletions bundler-plugins/astro.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import path from "node:path";

import vitePlugin from "./vite.mjs";


// ********************************

export default QRDS;


// ********************************

function QRDS() {
var command = null;
var vite = vitePlugin();

QRDS.vite = () => {
// copy a subset of the vite plugin hooks that are still
// necessary, even though astro plugin is mostly taking
// over the task
return {
name: vite.name,
enforce: vite.enforce,
resolveId: vite.resolveId,
load: vite.load,
};
};

return {
name: "astro-plugin-qrds",
hooks: {
["astro:config:setup"](options) {
command = options.command;
options.injectScript(
"head-inline",
`{let el=document.createElement("script");el.async=false;el.src="/qrds-external-bundle.js";document.head.appendChild(el);}`
);
},
["astro:config:done"](options) {
// call the underlying vite plugin's `configResolved()` hook,
// passing along to it (an artificial subset of) its expected
// `config` object
vite.configResolved({
command: (
command == "dev" ? "serve" :

[ "preview", "build", ].includes(command) ? "build" :

// note: should not use this!
"unknown"
),
root: options.config.root.pathname,
publicDir: options.config.publicDir.pathname,
build: {
// note: vite expects this to be relative to root
outDir: options.config.outDir.pathname.replace(options.config.root.pathname,""),
},
});
},
},
};
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"name": "@lo-fi/qr-data-sync",
"description": "Browser-only utils for sharing/synchronizing data using 'animated' QR codes",
"version": "0.999.1",
"version": "0.999.2",
"exports": {
".": "./dist/bundlers/qrds.mjs",
"./bundlers/astro": "./bundler-plugins/astro.mjs",
"./bundlers/vite": "./bundler-plugins/vite.mjs",
"./bundlers/webpack": "./bundler-plugins/webpack.mjs"
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/build-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ function matchesSkipPattern(pathStr,skipPatterns) {
async function safeMkdir(pathStr) {
if (!fs.existsSync(pathStr)) {
try {
await fsp.mkdir(pathStr,0o755);
await fsp.mkdir(pathStr,{ recursive: true, mode: 0o755, });
return true;
}
catch (err) {}
Expand Down
2 changes: 1 addition & 1 deletion scripts/build-gh-pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function matchesSkipPattern(pathStr,skipPatterns) {
async function safeMkdir(pathStr) {
if (!fs.existsSync(pathStr)) {
try {
await fsp.mkdir(pathStr,0o755);
await fsp.mkdir(pathStr,{ recursive: true, mode: 0o755, });
return true;
}
catch (err) {}
Expand Down

0 comments on commit 439a7e9

Please sign in to comment.