@@ -130,11 +130,11 @@ A complete implementation should provide the same safety contract developers exp
|
|||||||
|
|
||||||
### 1. Add an Effect View refresh transform
|
### 1. Add an Effect View refresh transform
|
||||||
|
|
||||||
Ship a Vite plugin, for example `@effect-view/vite`, placed before `react()`:
|
Ship a Vite plugin, `@effect-view/vite-plugin`, placed before `react()`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
plugins: [
|
plugins: [
|
||||||
effectViewRefresh(),
|
effectViewPlugin(),
|
||||||
react(),
|
react(),
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
"react-icons": "^5.6.0",
|
"react-icons": "^5.6.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@effect-view/vite": "workspace:*",
|
"@effect-view/vite-plugin": "workspace:*",
|
||||||
"@tanstack/react-router": "^1.170.10",
|
"@tanstack/react-router": "^1.170.10",
|
||||||
"@tanstack/react-router-devtools": "^1.167.0",
|
"@tanstack/react-router-devtools": "^1.167.0",
|
||||||
"@tanstack/router-plugin": "^1.168.13",
|
"@tanstack/router-plugin": "^1.168.13",
|
||||||
@@ -124,8 +124,8 @@
|
|||||||
"vite": "^8.0.16",
|
"vite": "^8.0.16",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/vite": {
|
"packages/vite-plugin": {
|
||||||
"name": "@effect-view/vite",
|
"name": "@effect-view/vite-plugin",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
@@ -574,7 +574,7 @@
|
|||||||
|
|
||||||
"@effect-fc/example-next": ["@effect-fc/example-next@workspace:packages/example-next"],
|
"@effect-fc/example-next": ["@effect-fc/example-next@workspace:packages/example-next"],
|
||||||
|
|
||||||
"@effect-view/vite": ["@effect-view/vite@workspace:packages/vite"],
|
"@effect-view/vite-plugin": ["@effect-view/vite-plugin@workspace:packages/vite-plugin"],
|
||||||
|
|
||||||
"@effect/language-service": ["@effect/language-service@0.86.6", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-uwXbp+lWzt60bZnm6lG6S5DWy0m6TthUzV2hcQoiS6NzieEDm07tuBakscxOXoO+AU9+yTH+0TSIa9mEDt9dFA=="],
|
"@effect/language-service": ["@effect/language-service@0.86.6", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-uwXbp+lWzt60bZnm6lG6S5DWy0m6TthUzV2hcQoiS6NzieEDm07tuBakscxOXoO+AU9+yTH+0TSIa9mEDt9dFA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type * as Component from "./Component.js"
|
|||||||
* development refresh cell.
|
* development refresh cell.
|
||||||
*
|
*
|
||||||
* This low-level API is intended for development-server integrations such as
|
* This low-level API is intended for development-server integrations such as
|
||||||
* `@effect-view/vite`.
|
* `@effect-view/vite-plugin`.
|
||||||
*/
|
*/
|
||||||
export const RefreshableTypeId: unique symbol = Symbol.for("@effect-view/Refreshable/Refreshable")
|
export const RefreshableTypeId: unique symbol = Symbol.for("@effect-view/Refreshable/Refreshable")
|
||||||
export type RefreshableTypeId = typeof RefreshableTypeId
|
export type RefreshableTypeId = typeof RefreshableTypeId
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"clean:modules": "rm -rf node_modules"
|
"clean:modules": "rm -rf node_modules"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@effect-view/vite": "workspace:*",
|
"@effect-view/vite-plugin": "workspace:*",
|
||||||
"@tanstack/react-router": "^1.170.10",
|
"@tanstack/react-router": "^1.170.10",
|
||||||
"@tanstack/react-router-devtools": "^1.167.0",
|
"@tanstack/react-router-devtools": "^1.167.0",
|
||||||
"@tanstack/router-plugin": "^1.168.13",
|
"@tanstack/router-plugin": "^1.168.13",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { tanstackRouter } from "@tanstack/router-plugin/vite"
|
import { tanstackRouter } from "@tanstack/router-plugin/vite"
|
||||||
import react from "@vitejs/plugin-react"
|
import react from "@vitejs/plugin-react"
|
||||||
import effectViewRefresh from "@effect-view/vite"
|
import { effectViewPlugin } from "@effect-view/vite-plugin"
|
||||||
import path from "node:path"
|
import path from "node:path"
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import { defineConfig } from "vite"
|
|||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
effectViewRefresh(),
|
effectViewPlugin(),
|
||||||
tanstackRouter({
|
tanstackRouter({
|
||||||
target: "react",
|
target: "react",
|
||||||
autoCodeSplitting: true,
|
autoCodeSplitting: true,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
# `@effect-view/vite`
|
# `@effect-view/vite-plugin`
|
||||||
|
|
||||||
Experimental Vite Fast Refresh support for Effect View components.
|
Experimental Vite Fast Refresh support for Effect View components.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import effectViewRefresh from "@effect-view/vite"
|
import { effectViewPlugin } from "@effect-view/vite-plugin"
|
||||||
import react from "@vitejs/plugin-react"
|
import react from "@vitejs/plugin-react"
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
effectViewRefresh(),
|
effectViewPlugin(),
|
||||||
react(),
|
react(),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@effect-view/vite",
|
"name": "@effect-view/vite-plugin",
|
||||||
"description": "Vite Fast Refresh support for Effect View components",
|
"description": "Vite Fast Refresh support for Effect View components",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -42,7 +42,7 @@ interface Definition {
|
|||||||
|
|
||||||
const defaultInclude = /\.[cm]?[jt]sx?$/
|
const defaultInclude = /\.[cm]?[jt]sx?$/
|
||||||
const defaultExclude = /\/node_modules\//
|
const defaultExclude = /\/node_modules\//
|
||||||
const runtimeImport = "@effect-view/vite/runtime"
|
const runtimeImport = "@effect-view/vite-plugin/runtime"
|
||||||
const refreshIdentifier = "__effectViewRefresh"
|
const refreshIdentifier = "__effectViewRefresh"
|
||||||
const acceptIdentifier = "__effectViewAccept"
|
const acceptIdentifier = "__effectViewAccept"
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ const scriptKind = (id: string): ts.ScriptKind => id.endsWith(".tsx")
|
|||||||
*
|
*
|
||||||
* Place this plugin before `@vitejs/plugin-react`.
|
* Place this plugin before `@vitejs/plugin-react`.
|
||||||
*/
|
*/
|
||||||
export default function effectViewRefresh(
|
export function effectViewPlugin(
|
||||||
options: EffectViewRefreshOptions = {},
|
options: EffectViewRefreshOptions = {},
|
||||||
): Plugin {
|
): Plugin {
|
||||||
const include = options.include ?? defaultInclude
|
const include = options.include ?? defaultInclude
|
||||||
@@ -30,7 +30,7 @@ const getRefreshData = (hot: HotContext): RefreshData => {
|
|||||||
/**
|
/**
|
||||||
* Registers an Effect View descriptor in a Vite HMR data cell.
|
* Registers an Effect View descriptor in a Vite HMR data cell.
|
||||||
*
|
*
|
||||||
* This API is injected by `@effect-view/vite`; applications should not need to
|
* This API is injected by `@effect-view/vite-plugin`; applications should not need to
|
||||||
* call it directly.
|
* call it directly.
|
||||||
*/
|
*/
|
||||||
export const register = <A extends Component.Component.Any>(
|
export const register = <A extends Component.Component.Any>(
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import path from "node:path"
|
import path from "node:path"
|
||||||
import type { Plugin, TransformPluginContext } from "vite"
|
import type { Plugin, TransformPluginContext } from "vite"
|
||||||
import { describe, expect, it } from "vitest"
|
import { describe, expect, it } from "vitest"
|
||||||
import effectViewRefresh from "../src/index.js"
|
import { effectViewPlugin } from "../src/index.js"
|
||||||
|
|
||||||
|
|
||||||
const runTransform = async (
|
const runTransform = async (
|
||||||
@@ -25,9 +25,9 @@ const runTransform = async (
|
|||||||
const transform = (
|
const transform = (
|
||||||
code: string,
|
code: string,
|
||||||
id = path.join(process.cwd(), "src/View.tsx"),
|
id = path.join(process.cwd(), "src/View.tsx"),
|
||||||
): Promise<string | undefined> => runTransform(effectViewRefresh(), code, id)
|
): Promise<string | undefined> => runTransform(effectViewPlugin(), code, id)
|
||||||
|
|
||||||
describe("effectViewRefresh", () => {
|
describe("effectViewPlugin", () => {
|
||||||
it("wraps a const Effect View descriptor", async () => {
|
it("wraps a const Effect View descriptor", async () => {
|
||||||
const result = await transform(`
|
const result = await transform(`
|
||||||
import { Component } from "effect-fc-next"
|
import { Component } from "effect-fc-next"
|
||||||
@@ -39,7 +39,7 @@ export const CounterView = Component.make("CounterView")(function*() {
|
|||||||
})
|
})
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(result).toContain("import { accept as __effectViewAccept, register as __effectViewRefresh } from \"@effect-view/vite/runtime\"")
|
expect(result).toContain("import { accept as __effectViewAccept, register as __effectViewRefresh } from \"@effect-view/vite-plugin/runtime\"")
|
||||||
expect(result).toContain("__effectViewRefresh(Component.make(\"CounterView\")")
|
expect(result).toContain("__effectViewRefresh(Component.make(\"CounterView\")")
|
||||||
expect(result).toContain("\"src/View.tsx:CounterView\"")
|
expect(result).toContain("\"src/View.tsx:CounterView\"")
|
||||||
expect(result).toContain("__effectViewAccept(import.meta.hot, [\"src/View.tsx:CounterView\"])")
|
expect(result).toContain("__effectViewAccept(import.meta.hot, [\"src/View.tsx:CounterView\"])")
|
||||||
@@ -103,7 +103,7 @@ export function View() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("keeps instrumenting a module when all Effect Views are removed", async () => {
|
it("keeps instrumenting a module when all Effect Views are removed", async () => {
|
||||||
const plugin = effectViewRefresh() as Plugin
|
const plugin = effectViewPlugin() as Plugin
|
||||||
const id = path.join(process.cwd(), "src/Removed.tsx")
|
const id = path.join(process.cwd(), "src/Removed.tsx")
|
||||||
|
|
||||||
await runTransform(plugin, `
|
await runTransform(plugin, `
|
||||||
Reference in New Issue
Block a user