diff --git a/.changeset/nice-loops-decide.md b/.changeset/nice-loops-decide.md new file mode 100644 index 00000000..5881d9fa --- /dev/null +++ b/.changeset/nice-loops-decide.md @@ -0,0 +1,5 @@ +--- +'@tanstack/devtools-vite': minor +--- + +Allow the vite plugin to remove the devtools completely from the build output bundle for 0 production footprint diff --git a/README.md b/README.md index b9d15c4e..55eead88 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Coming soon... #TanStack - + + @@ -48,15 +48,25 @@ Try other [TanStack](https://tanstack.com) libraries: You may know **TanSack Devtools** by our adapter names, too! -- [**React Devtools**](https://tanstack.com/devtools/latest/docs/framework/react/react-devtools) +- [**React Devtools**](https://tanstack.com/devtools/latest/docs/framework/react/basic-setup) +- [**Solid Devtools**](https://tanstack.com/devtools/latest/docs/framework/solid/basic-setup) ## Summary -Coming soon... +TanStack Devtools is a powerful set of tools designed to help developers inspect and debug applications built with various frameworks, including React, Solid, and Vanilla JS. It provides a unified interface to monitor application state, track changes, and identify issues in real-time. + +It is built with a plugin architecture, allowing for easy extension and customization. The devtools vite plugin can be integrated into your application, which enhances the development experience by providing better console logs, a server event bus, and improved debugging capabilities. ## Quick Features -Coming soon... +- Inspect and debug your application's state and behavior in real-time +- Support for multiple frameworks (React, Solid, Vanilla JS, etc.) +- Plugin architecture to extend functionality +- Production mode support with tree-shaking to remove devtools code +- Customizable UI +- Event bus for communication between the devtools and your application +- Go-to-source functionality for easy debugging +- Works seamlessly with TanStack Query, Router, and other TanStack libraries ## Installation diff --git a/docs/config.json b/docs/config.json index cba5cea6..0933140e 100644 --- a/docs/config.json +++ b/docs/config.json @@ -28,6 +28,10 @@ { "label": "Vite plugin", "to": "vite-plugin" + }, + { + "label": "Production", + "to": "production" } ], "frameworks": [ @@ -140,4 +144,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md index 19ff5b44..154c6597 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -10,7 +10,7 @@ Only install one of the following packages depending on your use case: ## React ```sh -npm install @tanstack/react-devtools +npm install -D @tanstack/react-devtools npm install -D @tanstack/devtools-vite ``` @@ -19,7 +19,7 @@ TanStack Devtools is compatible with React v16.8+ ## Solid ```sh -npm install @tanstack/solid-devtools +npm install -D @tanstack/solid-devtools npm install -D @tanstack/devtools-vite ``` @@ -28,7 +28,25 @@ TanStack Devtools is compatible with Solid v1.9.5+ ## Vanilla JS ```sh -npm install @tanstack/devtools +npm install -D @tanstack/devtools ``` Install the the core `@tanstack/devtools` package to use with any framework or without a framework. Each framework package up above will also re-export everything from this core package. + + +## Production Builds + +If you want to have the devtools in production builds, you can install the core `@tanstack/devtools` package as a regular dependency: + +```sh +npm install @tanstack/devtools +npm install -D @tanstack/devtools-vite +``` + +And then import from the `/production` subpath: + +```ts +import { TanStackDevtools } from '@tanstack/devtools/production' +``` + +Read more about using the devtools in production in our [Production docs](https://tanstack.com/devtools/latest/docs/production). \ No newline at end of file diff --git a/docs/production.md b/docs/production.md new file mode 100644 index 00000000..aa0ca1d4 --- /dev/null +++ b/docs/production.md @@ -0,0 +1,53 @@ +--- +title: Production +id: production +--- + +> [!IMPORTANT] This document and the underlying implementation is actively being worked on internally and may be incomplete or inaccurate and is highly likely to change! + +The whole point of devtools is to help you during development, so it's generally not recommended to include them in production builds, but if you know what you're doing, you can. + +## Production Exports + +Every package under the `devtools` umbrella should provide a `/production` sub-export that will +allow you to use the devtools in production builds. The normal root export will always be stripped out of production builds by default. + +```ts +// This will be included in production builds +import { TanStackDevtools } from '@tanstack/react-devtools/production' +// This will be replaced by a function that returns null in production builds +import { TanStackDevtools } from '@tanstack/react-devtools' +``` + +This is subject to change and might be offloaded to the Vite plugin in the future as we continue to build out the production story and close in on the best DX and the v1 release. + +## Vite Plugin Configuration + +The default behavior of the Vite plugin is to remove all devtools related code from the production build. This is usually what you want, but if you want to keep the devtools in production (not recommended) you can set the `removeDevtoolsOnBuild` option to `false`. + +```ts +import { devtools } from '@tanstack/devtools-vite' + +export default { + plugins: [ + devtools({ + removeDevtoolsOnBuild: false + }), + // ... rest of your plugins here + ], +} +``` + +This will include the devtools in your production build, but keep in mind, you still need the `/production` sub-export to actually get the production version of the devtools. + +## Where to install the Devtools + +If you are using the devtools in development only, you can install them as a development dependency and only import them in development builds. This is the default recommended way to use the devtools. + +If you are using the devtools in production, you need to install them as a regular dependency and import them in your application code. + +## Development / Production workflow + +For Development, you can install the devtools as a development dependency and import them in your application code. The Vite plugin will take care of stripping them out of the production build. + +For Production, you can install the devtools as a regular dependency and import them in your application code using the `/production` sub-export and then you also need to set `removeDevtoolsOnBuild` to `false` in the Vite plugin configuration. \ No newline at end of file diff --git a/docs/vite-plugin.md b/docs/vite-plugin.md index cc248e27..75d22bd2 100644 --- a/docs/vite-plugin.md +++ b/docs/vite-plugin.md @@ -118,6 +118,22 @@ export default { } ``` +### removeDevtoolsOnBuild + +Whether to remove devtools from the production build. Defaults to true. + +```ts +import { devtools } from '@tanstack/devtools-vite' +export default { + plugins: [ + devtools({ + removeDevtoolsOnBuild: true + }), + // ... rest of your plugins here + ], +} +``` + ### injectSource Configuration for source injection. Defaults to enabled. diff --git a/examples/react/basic/vite.config.ts b/examples/react/basic/vite.config.ts index ff6cabe2..5ea9c49a 100644 --- a/examples/react/basic/vite.config.ts +++ b/examples/react/basic/vite.config.ts @@ -6,7 +6,9 @@ import Inspect from 'vite-plugin-inspect' // https://vite.dev/config/ export default defineConfig({ plugins: [ - devtools(), + devtools({ + removeDevtoolsOnBuild: true, + }), Inspect(), react({ // babel: { diff --git a/packages/devtools-vite/tests/inject-source.test.ts b/packages/devtools-vite/src/inject-source.test.ts similarity index 99% rename from packages/devtools-vite/tests/inject-source.test.ts rename to packages/devtools-vite/src/inject-source.test.ts index edc0fb52..b145f799 100644 --- a/packages/devtools-vite/tests/inject-source.test.ts +++ b/packages/devtools-vite/src/inject-source.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { addSourceToJsx } from '../src/inject-source' +import { addSourceToJsx } from './inject-source' const removeEmptySpace = (str: string) => { return str.replace(/\s/g, '').trim() diff --git a/packages/devtools-vite/src/plugin.ts b/packages/devtools-vite/src/plugin.ts index dfe2669a..7f08110d 100644 --- a/packages/devtools-vite/src/plugin.ts +++ b/packages/devtools-vite/src/plugin.ts @@ -3,6 +3,7 @@ import chalk from 'chalk' import { ServerEventBus } from '@tanstack/devtools-event-bus/server' import { handleDevToolsViteRequest } from './utils' import { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor' +import { removeDevtools } from './remove-devtools' import { addSourceToJsx } from './inject-source' import type { EditorConfig } from './editor' import type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server' @@ -27,6 +28,11 @@ export type TanStackDevtoolsViteConfig = { */ enabled: boolean } + /** + * Whether to remove devtools from the production build. + * @default true + */ + removeDevtoolsOnBuild?: boolean /** * Configuration for source injection. */ @@ -46,6 +52,7 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array => { let port = 5173 const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true } const injectSourceConfig = args?.injectSource ?? { enabled: true } + const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true const bus = new ServerEventBus(args?.eventBusConfig) return [ @@ -116,6 +123,24 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array => { ) }, }, + { + name: '@tanstack/devtools:remove-devtools-on-build', + apply(_, { command }) { + return command === 'build' && removeDevtoolsOnBuild + }, + enforce: 'pre', + transform(code, id) { + if ( + id.includes('node_modules') || + id.includes('?raw') || + id.includes('dist') || + id.includes('build') + ) + return code + + return removeDevtools(code, id) + }, + }, { name: '@tanstack/devtools:better-console-logs', enforce: 'pre', diff --git a/packages/devtools-vite/src/remove-devtools.test.ts b/packages/devtools-vite/src/remove-devtools.test.ts new file mode 100644 index 00000000..474b3698 --- /dev/null +++ b/packages/devtools-vite/src/remove-devtools.test.ts @@ -0,0 +1,230 @@ +import { describe, expect, test } from 'vitest' +import { removeDevtools } from './remove-devtools' + +const removeEmptySpace = (str: string) => { + return str.replace(/\s/g, '').trim() +} + +describe('remove-devtools', () => { + test('it removes devtools if Imported directly', () => { + const output = removeEmptySpace( + removeDevtools( + ` + import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools' +import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools' +import { + Link, + Outlet, + RouterProvider, + createRootRoute, + createRoute, + createRouter, +} from '@tanstack/react-router' +import { TanStackDevtools } from '@tanstack/react-devtools' + + + +export default function DevtoolsExample() { + return ( + <> + , + }, + { + name: 'TanStack Router', + render: , + }, + /* { + name: "The actual app", + render: