Skip to content

Commit

Permalink
docs: env plugin updates (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev authored Jul 22, 2024
1 parent 9534d17 commit b8f5a67
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
type: lesson
title: Env variables in load hook
title: Env variables in the load hook
focus: /vite.config.ts
mainCommand: ""
terminal:
Expand All @@ -9,11 +9,11 @@ terminal:
- ["terminal", "Terminal"]
---

# Env variables in load hook
# Env variables in the load hook

We are now able to intercept loading of the virtual module and have prevented other plugins from colliding with it.
We are now able to intercept the loading of the virtual module and have prevented other plugins from colliding with it.

Next we'll need to handle the actual environment variables. As environment variables are an easy way to expose secrets, let's allow our plugin to only expose variables that are prefixed with `TUTORIAL_`:
Next, we'll need to handle the actual environment variables. As environment variables are an easy way to expose secrets, let's extend our plugin to only expose variables that are prefixed with `TUTORIAL_`:

```ts
function getTutorialEnvVariables() {
Expand Down Expand Up @@ -42,7 +42,7 @@ load(id, options) {
},
```

Next let's open up the terminal and start Vite server while providing an environment variable:
Next, let's open up the terminal and start Vite server while providing an environment variable:

```sh
TUTORIAL_MY_MESSAGE="Hello world" npm run dev
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
type: lesson
title: Environment Variables in Node
title: Vite Env plugin
focus: /index.js
previews: false
template: empty
Expand All @@ -14,26 +14,26 @@ terminal:

# Vite Env plugin

In this part we'll be creating a plugin that allows us to use environment variables from virtual module.
By "virtual" we mean a module that doesn't really exist on file system but is provided by a Vite plugin in runtime.
In this chapter, we'll be creating a plugin that allows us to use environment variables from a virtual module.
By "virtual" we mean a module that doesn't exist on the file system but is provided by a Vite plugin in runtime.

We'll be defining a module entrypoint for `"virtual:tutorial-env"`. Note that `virtual:` is a [convention of Vite virtual modules](https://vitejs.dev/guide/api-plugin#virtual-modules-convention).
We'll define a module entry point for `"virtual:tutorial-env"`. Note that `virtual:` is a [virtual modules convention](https://vitejs.dev/guide/api-plugin#virtual-modules-convention).

```ts
import env from "virtual:tutorial-env";
```

But first let's take a look at how environment variables work in Node.
But first, let's take a look at how environment variables work in Node.

- On Unix systems environment variables can be passed to commands by defining them before command itself
- On Unix systems environment variables can be passed to commands by defining them before the command itself

```sh
TUTORIAL_MESSAGE=Hello node index.js
```

<br aria-hidden />

- Environments variables are available in [`process.env`](https://nodejs.org/api/process.html#processenv)
- Environment variables are available in [`process.env`](https://nodejs.org/api/process.html#processenv)
```js
console.log(process.env.TUTORIAL_MESSAGE);
// Hello
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
type: lesson
title: Importing virtual module
title: Importing a virtual module
focus: /index.js
---

# Importing virtual module
# Importing a virtual module

Now that we know how environment variables work, let's continue with our custom plugin!

Add an import for the virtual module in `index.js`. At this point it should break our Vite setup but that's fine!
Add an import for the virtual module in `index.js`. At this point, it should break our Vite setup but that's fine!

```ts add={1,2} del={3}
import env from "virtual:tutorial-env";
Expand All @@ -31,7 +31,7 @@ export default defineConfig({
});
```

In the previous lessons we saw that a plugin can intercept module request in the `load()` hook. Let's try using the same trick here.
In the previous chapter, we saw that a plugin can intercept module requests in the `load()` hook. Let's try using the same trick here.

```ts
{
Expand All @@ -44,7 +44,7 @@ In the previous lessons we saw that a plugin can intercept module request in the
},
```

Even when we are handling the loading of the file, Vite keeps showing an error. Note how this error is thrown by another Vite plugin - Vite's internal `plugin:vite:import-analysis`.
Even when we are handling the file loading, Vite keeps showing an error. Note how this error is thrown by another Vite plugin - Vite's internal `plugin:vite:import-analysis`.

> [plugin:vite:import-analysis] Failed to resolve import "virtual:tutorial-env" from "index.js". Does the file exist?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
---
type: lesson
title: Resolving id of virtual module
title: Resolving the id of a virtual module
focus: /vite.config.ts
---

# Resolving id of virtual module
# Resolving the id of a virtual module

Our plugin is now able to load the virtual module. But there are other Vite plugins failing as they also attempt to load it.
Our plugin is now able to load the virtual module. But other Vite plugins are failing as they also attempt to load it.

To solve this we'll need to internally mark the virtual module with a special prefix so that other plugins will know to skip it. There's [a convention](https://vitejs.dev/guide/api-plugin#virtual-modules-convention) of using `\0` in the internal module ids - let's add that!
To solve this we'll need to internally mark the virtual module with a special prefix so that other plugins skip it. There's [a convention](https://vitejs.dev/guide/api-plugin#virtual-modules-convention) of using `\0` in the internal module ids - let's add that!

Vite will internally resolve ids for each requested module using the `resolveId` hook. Add this to the plugin:
Vite internally resolve ids for each requested module using the `resolveId` hook. Add this to the plugin:

```ts add={3}
{
Expand All @@ -24,7 +24,7 @@ Vite will internally resolve ids for each requested module using the `resolveId`
}
```

Next we'll need to use the special `\0` prefix in the resolved id. We can simply look for our virtual module's entrypoint and return that with the prefix:
Next, we need to prefix the resolved id using the special `\0` marker. Once `resolveId` is called for our virtual module's entry point, we'll return it with this prefix:

```ts
{
Expand All @@ -42,9 +42,7 @@ Next we'll need to use the special `\0` prefix in the resolved id. We can simply
}
```

Perfect - the error from Vite's internal `plugin:vite:import-analysis` is now gone! But `index.js` still fails to load.

To fix this we'll need to apply the `\0` prefix in the `load()` hook as well:
Perfect - the error from Vite's internal `plugin:vite:import-analysis` is now gone! But `index.js` still fails to load. The `load()` hook receives the resolved ids, so we need to be checking for the `\0` prefix in it as well:

```ts add={9} del={10}
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ terminal:

# Summarize

We've now built a plugin for providing entrypoint for virtual modules. Let's summarize the process:
We've now built a plugin for providing entry point for virtual modules. Let's summarize the process:

<ol>
<li>Source code requests virtual module: <code class="whitespace-nowrap">import env from "virtual:tutorial-env"</code>

<li class="mt2">Vite plugin's <code>resolveId()</code> is called to ask an internal id for the file. Hook returns an id and prefixes it with <code>\0</code>.</li>
<li class="mt2">Our Vite plugin's <code>resolveId()</code> is called to resolve the id for each imported module specifier. In our plugin, this hook returns an id prefixed with the <code>\0</code> marker, a convention to let other plugins know that this is a virtual module.</li>

<li class="mt2">Vite plugin's <code>load()</code> is called with the internal id. Our custom plugin recognizes this id.</li>
<li class="mt2">Our Vite plugin's <code>load()</code> is called with the resolved id. Our custom plugin recognizes this id.</li>

<li class="mt2">Other Vite plugins see <code>\0</code> prefix and know to skip this module</li>

<li class="mt2">Custom plugin reads host machine's environment variables from <code>process.end</code> and collects the <code>TUTORIAL_</code> prefixed variables.</li>
<li class="mt2">A custom plugin reads the host machine's environment variables from <code>process.end</code> and collects the <code>TUTORIAL_</code> prefixed variables.</li>

<li class="mt2">Javascript object is serialized into text using <code>JSON.stringify()</code> and returned as default export from <code>load()</code> hook</li>
<li class="mt2">A JavaScript object is serialized into text using <code>JSON.stringify()</code> and returned as the default export from <code>load()</code> hook</li>

<li class="mt2">Source code successfully loads the virtual module&nbsp;✅</li>
<li class="mt2">The source code successfully loads the virtual module&nbsp;✅</li>
</ol>

📚 Homework: Build a Vite plugin that provides virtual module for importing version of your package - `import { version } from "virtual:tutorial-assignment"`. It should read the `"version"` field from `package.json` and return it as named export.
📚 Homework: Build a Vite plugin that provides a virtual module for importing version of your package - `import { version } from "virtual:tutorial-assignment"`. It should read the `"version"` field from `package.json` and return it as a named export.

0 comments on commit b8f5a67

Please sign in to comment.