diff --git a/.changeset/fair-pets-crash.md b/.changeset/fair-pets-crash.md
new file mode 100644
index 000000000..75a03f602
--- /dev/null
+++ b/.changeset/fair-pets-crash.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/vite-plugin-svelte': major
+---
+
+Remove experimental "advanced raw queries" feature. Basic `File.svelte?raw` is still supported.
diff --git a/.changeset/shiny-hats-move.md b/.changeset/shiny-hats-move.md
new file mode 100644
index 000000000..3a6db49f7
--- /dev/null
+++ b/.changeset/shiny-hats-move.md
@@ -0,0 +1,6 @@
+---
+'@sveltejs/vite-plugin-svelte-inspector': patch
+'@sveltejs/vite-plugin-svelte': patch
+---
+
+use vite environment api internally
diff --git a/.changeset/thirty-roses-tell.md b/.changeset/thirty-roses-tell.md
new file mode 100644
index 000000000..9935da02e
--- /dev/null
+++ b/.changeset/thirty-roses-tell.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/vite-plugin-svelte': major
+---
+
+split preprocess and compile into separate plugins
diff --git a/.changeset/two-facts-sink.md b/.changeset/two-facts-sink.md
new file mode 100644
index 000000000..babffa5eb
--- /dev/null
+++ b/.changeset/two-facts-sink.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/vite-plugin-svelte': patch
+---
+
+deprecate `plugin.api.sveltePreprocess`
diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md
index 4d7583db8..805d36572 100644
--- a/docs/advanced-usage.md
+++ b/docs/advanced-usage.md
@@ -7,6 +7,50 @@
>
> **Proceed with caution!**
+## transform svelte files with vite plugins
+
+vite-plugin-svelte uses 2 Vite plugins `vite-plugin-svelte:preprocess` and `vite-plugin-svelte:compile` to preprocess and compile input.
+The preprocess plugin uses `enforce: pre` but the compile plugin does not, giving you fine-grained control to add your own transforms
+
+```js
+function mySvelteTransform() {
+ const plugin = {
+ name: 'vite-plugin-my-svelte-transformer',
+ configResolved(c) {
+ // optional, use the exact same id filter as vite-plugin-svelte itself
+ const svelteIdFilter = c.plugins.find((p) => p.name === 'vite-plugin-svelte:config').api
+ .idFilter;
+ plugin.transform.filter.id = svelteIdFilter;
+ },
+ transform: {
+ // if you don't use vite-plugin-svelte's filter make sure to include your own here
+ filter: { id: /your id filter here/ },
+ async handler(code, id) {
+ const s = new MagicString(code);
+ // do your transforms with s
+ return {
+ code: s.toString(),
+ map: s.generateMap({ hires: 'boundary', includeContent: false })
+ };
+ }
+ }
+ };
+ // To add your transform in the correct place use `enforce` and `transform.order`
+
+ // before preprocess
+ plugin.enforce = 'pre';
+ plugin.transform.order = 'pre';
+
+ // after preprocess but before compile
+ plugin.transform.order = 'pre'; // leave plugin.enforce undefined
+
+ // after compile
+ plugin.transform.order = 'post'; // leave plugin.enforce undefined
+
+ return plugin;
+}
+```
+
## custom queries
Vite supports using query parameters to request different outcomes for the same file.
@@ -19,103 +63,3 @@ The following schemes are supported by vite-plugin-svelte:
//get .svelte file content as a string
import content from 'File.svelte?raw';
```
-
-### experimental
-
-In addition to the plain .svelte source content, you can use special svelte queries.
-
-> These svelte subqueries are experimental, availability, syntax and output format may change
-
-#### raw&svelte
-
-```js
-//get output of svelte.preprocess code as string
-import preprocessed from 'File.svelte?raw&svelte&type=preprocessed';
-```
-
-```js
-//get output of svelte.compile js.code as string
-import script from 'File.svelte?raw&svelte&type=script';
-```
-
-```js
-//get output of svelte.compile css.code as string
-import style from 'File.svelte?raw&svelte&type=style';
-```
-
-##### detail exports
-
-raw&svelte exports code string as default export, but also offers named exports if you need details
-
-```js
-//get output of svelte.preprocess
-import { code, map, dependencies } from 'File.svelte?raw&svelte&type=preprocessed';
-```
-
-```js
-//get output of svelte.compile js
-import { code, map, dependencies } from 'File.svelte?raw&svelte&type=script';
-```
-
-```js
-//get output of svelte.compile css
-import { code, map, dependencies } from 'File.svelte?raw&svelte&type=style';
-```
-
-```js
-//get everything in one go
-import * as all from 'File.svelte?raw&svelte&type=all';
-import {
- source,
- preprocessed,
- dependencies,
- js,
- css,
- ast,
- normalizedFilename,
- ssr,
- lang,
- warnings,
- stats
-} from 'File.svelte?raw&svelte&type=all';
-```
-
-#### direct&svelte
-
-```html
-
-
-
-
-```
-
-#### sourcemap
-
-add `&sourcemap` to `?(raw|direct)&svelte&type=(script|style|all)` queries to include sourcemaps (inline for direct)
-
-#### compilerOptions
-
-?raw and ?direct use default compilerOptions, even if you have different values in your svelte.config.js:
-
-```js
-const compilerOptions = {
- dev: false,
- generate: 'client',
- css: 'external'
-};
-```
-
-to get output with different compilerOptions, append them as json like this:
-
-```js
-//get ssr output of svelte.compile js as {code, map, dependencies}
-import script from 'File.svelte?raw&svelte&type=script&compilerOptions={"generate":"server"}';
-```
-
-only a subset of compilerOptions is supported
-
-- generate
-- dev
-- css
-- customElement
-- immutable
diff --git a/docs/faq.md b/docs/faq.md
index 2f9b334a3..b49422155 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -82,19 +82,7 @@ However, `cssHash` is respected in production builds as HMR is a dev-only featur
### How do I add a Svelte preprocessor from a Vite plugin?
-If you are building a Vite plugin that transforms CSS or JS, you can add a `api.sveltePreprocess: PreprocessorGroup` to your Vite plugin definition and it will be added to the list of Svelte preprocessors used at runtime.
-
-```js
-const vitePluginCoolCss = {
- name: 'vite-plugin-coolcss',
- api: {
- sveltePreprocess: {
- /* your PreprocessorGroup here */
- }
- }
- /*... your cool css plugin implementation here .. */
-};
-```
+You don't have to anymore. See [advanced usage](advanced-usage.md) for examples how to put transform hooks before or after Svelte preprocess or compile
### What is going on with Vite and `Pre-bundling dependencies:`?
diff --git a/packages/e2e-tests/autoprefixer-browerslist/src/main.js b/packages/e2e-tests/autoprefixer-browerslist/src/main.js
index 47818da0c..071c75dc7 100644
--- a/packages/e2e-tests/autoprefixer-browerslist/src/main.js
+++ b/packages/e2e-tests/autoprefixer-browerslist/src/main.js
@@ -1,7 +1,3 @@
import App from './App.svelte';
-
-if (App.toString().startsWith('class ')) {
- new App({ target: document.body });
-} else {
- import('svelte').then(({ mount }) => mount(App, { target: document.body }));
-}
+import { mount } from 'svelte';
+mount(App, { target: document.body });
diff --git a/packages/e2e-tests/configfile-custom/svelte.config.ts b/packages/e2e-tests/configfile-custom/svelte.config.ts
new file mode 100644
index 000000000..e92845e0b
--- /dev/null
+++ b/packages/e2e-tests/configfile-custom/svelte.config.ts
@@ -0,0 +1,2 @@
+console.log('default svelte config loaded');
+export default {};
diff --git a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/preprocessed.txt b/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/preprocessed.txt
deleted file mode 100644
index a6320b265..000000000
--- a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/preprocessed.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
diff --git a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/ssr-preprocessed.txt b/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/ssr-preprocessed.txt
deleted file mode 100644
index a6320b265..000000000
--- a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/ssr-preprocessed.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
diff --git a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/style.txt b/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/style.txt
deleted file mode 100644
index 2e590fb1d..000000000
--- a/packages/e2e-tests/import-queries/__tests__/__snapshots__/svelte-5/style.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-button.svelte-d8vj6a {
- color: #000099;
-}
\ No newline at end of file
diff --git a/packages/e2e-tests/import-queries/__tests__/import-queries.spec.ts b/packages/e2e-tests/import-queries/__tests__/import-queries.spec.ts
index 74c680808..3ee27dadc 100644
--- a/packages/e2e-tests/import-queries/__tests__/import-queries.spec.ts
+++ b/packages/e2e-tests/import-queries/__tests__/import-queries.spec.ts
@@ -1,4 +1,4 @@
-import { browserLogs, fetchFromPage, getText, isBuild, testDir } from '~utils';
+import { browserLogs, getText, isBuild, testDir } from '~utils';
import { createServer, ViteDevServer } from 'vite';
import { VERSION } from 'svelte/compiler';
@@ -22,114 +22,6 @@ describe('raw', () => {
const result = await getText('#raw');
await expect(result).toMatchFileSnapshot(snapshotFilename('raw'));
});
-
- test('Dummy.svelte?raw&svelte&type=preprocessed', async () => {
- const result = await getText('#preprocessed');
- await expect(result).toMatchFileSnapshot(snapshotFilename('preprocessed'));
- });
-
- test('Dummy.svelte?raw&svelte&type=script', async () => {
- const result = await getText('#script');
- expect(result).toContain('export default function Dummy');
- });
-
- test('Dummy.svelte?raw&svelte&type=script&compilerOptions={"customElement":true}', async () => {
- const result = await getText('#wcScript');
- expect(result).toContain('$.create_custom_element(Dummy,');
- });
-
- test('Dummy.svelte?raw&svelte&type=style', async () => {
- const result = await getText('#style');
- await expect(result).toMatchFileSnapshot(snapshotFilename('style'));
- });
-
- test('Dummy.svelte?raw&svelte&type=all&sourcemap', async () => {
- const result = JSON.parse(await getText('#all'));
- expect(result.ast).toBeDefined();
- expect(result.js).toBeDefined();
- expect(result.js.code).toBeDefined();
- expect(result.js.map).toBeDefined();
- expect(result.css).toBeDefined();
- expect(result.css.code).toBeDefined();
- expect(result.css.map).toBeDefined();
- expect(result.preprocessed).toBeDefined();
- expect(result.preprocessed.code).toBeDefined();
- expect(result.preprocessed.map).toBeDefined();
- });
-
- describe.runIf(!isBuild)('mixed exports', () => {
- test('Dummy.svelte?raw&svelte&type=preprocessed', async () => {
- const module = await fetchFromPage('src/Dummy.svelte?raw&svelte&type=preprocessed').then(
- (res) => res.text()
- );
- expect(module).toContain('export const code="