Support custom svelte compiler options in @astrojs/svelte (#3181)

* updating svelte integration to allow custom user config

* test: adding a test to verify that svelte options are piped through the integration

* updating the README with docs on overridding svelte options

* chore: adding changeset

* fix: copy/paste bug in test validation

* removing temporary debug scripts
This commit is contained in:
Tony Sullivan 2022-04-22 17:59:20 +00:00 committed by GitHub
parent 738fb958c3
commit ce9a61e9fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 93 additions and 17 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/svelte': patch
---
`@astrojs/svelte` integration supports custom svelte compiler options

View file

@ -3,5 +3,7 @@ import svelte from '@astrojs/svelte';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [svelte()], integrations: [svelte({
extensions: ['.svelte', '.sve']
})],
}); });

View file

@ -0,0 +1,5 @@
<script lang="ts">
export let message: string;
</script>
<div id="svelte-custom-ext">{ message }</div>

View file

@ -1,5 +1,9 @@
--- ---
import TypeScript from '../components/TypeScript.svelte' import TypeScript from '../components/TypeScript.svelte'
// Using a custom extension to verify svelte options
// in astro.config.mjs are passed properly to the svelte integration
import Custom from '../components/Custom.sve'
--- ---
<html lang="en"> <html lang="en">
<head> <head>
@ -20,6 +24,7 @@ import TypeScript from '../components/TypeScript.svelte'
<body> <body>
<main> <main>
<TypeScript message="Hello, TypeScript" client:load /> <TypeScript message="Hello, TypeScript" client:load />
<Custom message="Hello, Custom Extensions" client:idle />
</main> </main>
</body> </body>
</html> </html>

View file

@ -22,6 +22,13 @@ describe('Svelte component', () => {
expect($('#svelte-ts').text()).to.equal('Hello, TypeScript'); expect($('#svelte-ts').text()).to.equal('Hello, TypeScript');
}); });
it('Works with custom Svelte config', async () => {
const html = await fixture.readFile('/typescript/index.html');
const $ = cheerio.load(html);
expect($('#svelte-custom-ext').text()).to.equal('Hello, Custom Extensions');
});
}); });
if (isWindows) return; if (isWindows) return;

View file

@ -63,3 +63,31 @@ Also check our [Astro Integration Documentation][astro-integration] for more on
[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ [astro-integration]: https://docs.astro.build/en/guides/integrations-guide/
[astro-ui-frameworks]: https://docs.astro.build/en/core-concepts/framework-components/#using-framework-components [astro-ui-frameworks]: https://docs.astro.build/en/core-concepts/framework-components/#using-framework-components
## Options
This integration is powered by `@sveltejs/vite-plugin-svelte`. To customize the Svelte compiler, options can be provided to the integration. See the `@sveltejs/vite-plugin-svelte` [docs](https://github.com/sveltejs/vite-plugin-svelte/blob/HEAD/docs/config.md) for more details.
### Default options
A few of the default options passed to the Svelte compiler are required to build properly for Astro and cannot be overridden.
```js
const defaultOptions = {
emitCss: true,
compilerOptions: { dev: isDev, hydratable: true },
preprocess: [
preprocess({
less: true,
sass: { renderSync: true },
scss: { renderSync: true },
stylus: true,
typescript: true,
}),
],
};
```
The `emitCss`, `compilerOptions.dev`, and `compilerOptions.hydratable` cannot be overridden.
Providing your own `preprocess` options **will** override the defaults - make sure to enable the preprocessor flags needed for your project.

View file

@ -1,6 +1,7 @@
import type { AstroIntegration, AstroRenderer } from 'astro'; import type { AstroIntegration, AstroRenderer } from 'astro';
import { svelte } from '@sveltejs/vite-plugin-svelte'; import { svelte } from '@sveltejs/vite-plugin-svelte';
import preprocess from 'svelte-preprocess'; import preprocess from 'svelte-preprocess';
import type { Options } from '@sveltejs/vite-plugin-svelte';
function getRenderer(): AstroRenderer { function getRenderer(): AstroRenderer {
return { return {
@ -10,38 +11,61 @@ function getRenderer(): AstroRenderer {
}; };
} }
function getViteConfiguration(isDev: boolean) { function getViteConfiguration(isDev: boolean, options?: Options | OptionsCallback) {
const defaultOptions = {
emitCss: true,
compilerOptions: { dev: isDev, hydratable: true },
preprocess: [
preprocess({
less: true,
sass: { renderSync: true },
scss: { renderSync: true },
stylus: true,
typescript: true,
}),
],
};
let resolvedOptions: Partial<Options>;
if (!options) {
resolvedOptions = defaultOptions;
} else if (typeof options === 'function') {
resolvedOptions = options(defaultOptions);
} else {
resolvedOptions = {
...options,
...defaultOptions,
compilerOptions: {
...options.compilerOptions,
// Always use dev and hydratable from defaults
...defaultOptions.compilerOptions,
},
// Ignore default preprocessor if the user provided their own
preprocess: options.preprocess ?? defaultOptions.preprocess,
};
}
return { return {
optimizeDeps: { optimizeDeps: {
include: ['@astrojs/svelte/client.js', 'svelte', 'svelte/internal'], include: ['@astrojs/svelte/client.js', 'svelte', 'svelte/internal'],
exclude: ['@astrojs/svelte/server.js'], exclude: ['@astrojs/svelte/server.js'],
}, },
plugins: [ plugins: [
svelte({ svelte(resolvedOptions),
emitCss: true,
compilerOptions: { dev: isDev, hydratable: true },
preprocess: [
preprocess({
less: true,
sass: { renderSync: true },
scss: { renderSync: true },
stylus: true,
typescript: true,
}),
],
}),
], ],
}; };
} }
export default function (): AstroIntegration { type OptionsCallback = (defaultOptions: Options) => Options;
export default function (options?: Options | OptionsCallback): AstroIntegration {
return { return {
name: '@astrojs/svelte', name: '@astrojs/svelte',
hooks: { hooks: {
// Anything that gets returned here is merged into Astro Config // Anything that gets returned here is merged into Astro Config
'astro:config:setup': ({ command, updateConfig, addRenderer }) => { 'astro:config:setup': ({ command, updateConfig, addRenderer }) => {
addRenderer(getRenderer()); addRenderer(getRenderer());
updateConfig({ vite: getViteConfiguration(command === 'dev') }); updateConfig({ vite: getViteConfiguration(command === 'dev', options) });
}, },
}, },
}; };