Skip to content

Commit

Permalink
feat(vite-plugin-svelte): experimental option to use vite transforms …
Browse files Browse the repository at this point in the history
…as svelte preprocessor (sveltejs#9)

* wip: prototype implmenentation of a svelte style preprocessor using vites css transform

* wip: cleanup code, ensure injectCss: false is passed, add option

* wip: add typescript preprocessor to vite preprocess
  • Loading branch information
dominikg authored Mar 12, 2021
1 parent c5cb875 commit 01dad3f
Show file tree
Hide file tree
Showing 16 changed files with 354 additions and 37 deletions.
6 changes: 6 additions & 0 deletions packages/playground/preprocess-with-vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode
.idea
node_modules
dist
dist-ssr

12 changes: 12 additions & 0 deletions packages/playground/preprocess-with-vite/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Svelte App</title>
</head>
<body>
<script type="module" src="/src/index.js"></script>
</body>
</html>
17 changes: 17 additions & 0 deletions packages/playground/preprocess-with-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "svite-preprocess-with-vite",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"devDependencies": {
"@svitejs/vite-plugin-svelte": "workspace:*",
"sass": "^1.32.8",
"stylus": "^0.54.8",
"svelte": "^3.35.0",
"svelte-hmr": "^0.12.9",
"vite": "^2.0.5"
}
}
3 changes: 3 additions & 0 deletions packages/playground/preprocess-with-vite/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions packages/playground/preprocess-with-vite/src/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts">
import Foo from './Foo.svelte'
const world: string = 'world' // edit world and save to see hmr update
</script>

<h1 class="foo">Hello {world}</h1>
<p>This is styled with scss using darken fn</p>
<Foo />

<style lang="scss">
$blue: blue;
p {
color: darken($blue, 20);
}
h1.foo {
color: $blue; /* change color an save to see hmr update */
}
</style>
15 changes: 15 additions & 0 deletions packages/playground/preprocess-with-vite/src/Foo.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
let foo: string = 'stylus'
export let bla: string = 'blub'
</script>

<h1>Styles with {foo} {bla}</h1>
<p class="note">cool, huh?</p>

<style lang="stylus">
/* prettier-ignore */
.note
color #ff3e00
h1
color magenta
</style>
7 changes: 7 additions & 0 deletions packages/playground/preprocess-with-vite/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import App from './App.svelte'

const app = new App({
target: document.body
})

export default app
18 changes: 18 additions & 0 deletions packages/playground/preprocess-with-vite/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const svelte = require('@svitejs/vite-plugin-svelte')
const { defineConfig } = require('vite')

module.exports = defineConfig(({ command, mode }) => {
const isProduction = mode === 'production'
return {
plugins: [
svelte({
hot: !isProduction,
emitCss: true,
useVitePreprocess: true
})
],
build: {
minify: isProduction
}
}
})
2 changes: 1 addition & 1 deletion packages/playground/windicss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"svelte": "^3.35.0",
"svelte-hmr": "^0.12.9",
"vite": "^2.0.5",
"vite-plugin-windicss": "^0.6.11"
"vite-plugin-windicss": "^0.7.1"
}
}
2 changes: 1 addition & 1 deletion packages/playground/windicss/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ body {

@media (min-width: 320px) {
body {
background-color: rebeccapurple;
background-color: white;
}
}
1 change: 1 addition & 0 deletions packages/vite-plugin-svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@types/es-module-lexer": "^0.3.0",
"@types/estree": "^0.0.46",
"@types/hash-sum": "^1.0.0",
"@windicss/plugin-utils": "^0.7.1",
"esbuild": "^0.8.57",
"locate-character": "^2.0.5",
"magic-string": "^0.25.7",
Expand Down
37 changes: 15 additions & 22 deletions packages/vite-plugin-svelte/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import {
IndexHtmlTransformContext,
ModuleNode,
Plugin,
UserConfig,
ViteDevServer
UserConfig
} from 'vite'

// @ts-ignore
Expand Down Expand Up @@ -54,37 +53,29 @@ export default function vitePluginSvelte(rawOptions: Options): Plugin {
root: process.cwd()
}

// updated in configureServer hook
// @ts-ignore
let server: ViteDevServer

let compileSvelte: Function

return {
name: 'vite-plugin-svelte',
// make sure our resolver runs before vite internal resolver to resolve svelte field correctly
enforce: 'pre',
config(config, { mode, command }): Partial<UserConfig> {
config(config): Partial<UserConfig> {
// setup logger
if (process.env.DEBUG) {
log.setLevel('debug')
} else if (config.logLevel) {
log.setLevel(config.logLevel)
}
// init compiler
compileSvelte = createCompileSvelte({
hot:
options.hot !== false &&
mode === 'development' &&
command === 'serve',
// TODO fix TS (sorry)
// @ts-ignore
hotApi: options?.hot?.hotApi,
// @ts-ignore
adapter: options?.hot?.adapter
})

// extra vite config
const extraViteConfig = {
esbuild: {
tsconfigRaw: {
compilerOptions: {
importsNotUsedAsValues: 'preserve'
}
}
},
optimizeDeps: {
exclude: [...SVELTE_IMPORTS]
},
Expand All @@ -94,17 +85,19 @@ export default function vitePluginSvelte(rawOptions: Options): Plugin {
}
}
log.debug('additional vite config', extraViteConfig)
return extraViteConfig
return extraViteConfig as Partial<UserConfig>
},

configResolved(config) {
options = resolveOptions(options, config)
requestParser = buildIdParser(options)
// init compiler
compileSvelte = createCompileSvelte(options, config)
},

configureServer(_server) {
configureServer(server) {
// eslint-disable-next-line no-unused-vars
server = _server
options.server = server
},

load(id, ssr) {
Expand Down
52 changes: 42 additions & 10 deletions packages/vite-plugin-svelte/src/utils/compile.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { CompileOptions, Processed, ResolvedOptions } from './options'
import {
CompileOptions,
PreprocessorGroup,
Processed,
ResolvedOptions
} from './options'
import { compile, preprocess, walk } from 'svelte/compiler'
// @ts-ignore
import { createMakeHot } from 'svelte-hmr'
import { SvelteRequest } from './id'
import { safeBase64Hash } from './hash'
import { log } from './log'
import { ResolvedConfig } from 'vite'
import { buildExtraPreprocessors } from './preprocess'

const _createCompileSvelte = (makeHot: Function) =>
const _createCompileSvelte = (
makeHot: Function,
extraPreprocessors: PreprocessorGroup[]
) =>
async function compileSvelte(
svelteRequest: SvelteRequest,
code: string,
Expand All @@ -29,8 +39,17 @@ const _createCompileSvelte = (makeHot: Function) =>
}

let preprocessed
const preprocessors = []
if (options.preprocess) {
preprocessed = await preprocess(code, options.preprocess, { filename })
if (Array.isArray(options.preprocess)) {
preprocessors.push(...options.preprocess)
} else {
preprocessors.push(options.preprocess)
}
}
preprocessors.push(...(extraPreprocessors || []))
if (preprocessors.length > 0) {
preprocessed = await preprocess(code, preprocessors, { filename })
if (preprocessed.dependencies)
dependencies.push(...preprocessed.dependencies)
if (preprocessed.map) finalCompilerOptions.sourcemap = preprocessed.map
Expand Down Expand Up @@ -83,20 +102,33 @@ const _createCompileSvelte = (makeHot: Function) =>
return result
}

export function createCompileSvelte({
hot = false,
hotApi = '',
adapter = ''
}) {
const makeHot = hot && createMakeHot({ walk, hotApi, adapter })
return _createCompileSvelte(makeHot)
function buildMakeHot(options: ResolvedOptions) {
const needsMakeHot =
options.hot !== false && options.isServe && !options.isProduction
if (needsMakeHot) {
// @ts-ignore
const hotApi = options?.hot?.hotApi
// @ts-ignore
const adapter = options?.hot?.adapter
return createMakeHot({ walk, hotApi, adapter, hotOptions: options.hot })
}
}

export function createCompileSvelte(
options: ResolvedOptions,
config: ResolvedConfig
) {
const makeHot = buildMakeHot(options)
const extraPreprocessors = buildExtraPreprocessors(options, config)
return _createCompileSvelte(makeHot, extraPreprocessors)
}

export interface Code {
code: string
map?: any
dependencies?: any[]
}

export interface Compiled {
js: Code
css: Code
Expand Down
8 changes: 7 additions & 1 deletion packages/vite-plugin-svelte/src/utils/options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-unused-vars */
import { ResolvedConfig } from 'vite'
import { ResolvedConfig, ViteDevServer } from 'vite'
import { log } from './log'
import { loadSvelteConfig } from './loadSvelteConfig'

Expand Down Expand Up @@ -163,13 +163,19 @@ export interface Options {
* do not return cached transform data
*/
disableTransformCache?: boolean

/**
* use vite as extra css preprocessor EXPERIMENTAL!
*/
useVitePreprocess?: boolean
}

export interface ResolvedOptions extends Options {
root: string
isProduction: boolean
isBuild?: boolean
isServe?: boolean
server?: ViteDevServer
}

// TODO import from appropriate places
Expand Down
Loading

0 comments on commit 01dad3f

Please sign in to comment.