Skip to content

Commit

Permalink
feat: transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed May 10, 2020
1 parent b7b9d85 commit 87ee998
Show file tree
Hide file tree
Showing 17 changed files with 239 additions and 43 deletions.
5 changes: 4 additions & 1 deletion playground/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
<TestCssModules />
<TestPreprocessors />
<TestAssets />
<TestSrcImport/>
<TestSrcImport />
<TestJsonImport />
<TestTs />
<TestJsx />
<TestAlias />
<TestTransform />
<h2>Async Component</h2>
<TestAsync />
</template>
Expand All @@ -36,6 +37,7 @@ import TestJsonImport from './TestJsonImport.vue'
import TestTs from './ts/TestTs.vue'
import TestJsx from './TestJsx.vue'
import TestAlias from './TestAlias.vue'
import TestTransform from './TestTransform.vue'
export default {
data: () => ({
Expand All @@ -55,6 +57,7 @@ export default {
TestTs,
TestJsx,
TestAlias,
TestTransform,
TestAsync: defineAsyncComponent(() => import('./TestAsync.vue'))
}
}
Expand Down
18 changes: 18 additions & 0 deletions playground/TestTransform.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<h2>Transforms</h2>
<div class="transform-scss">This should be cyan</div>
<div class="transform-js">{{ transformed }}</div>
</template>

<script>
import './testTransform.scss'
import { __TEST_TRANSFORM__ } from './testTransform.js'
export default {
data() {
return {
transformed: __TEST_TRANSFORM__
}
}
}
</script>
14 changes: 14 additions & 0 deletions playground/plugins/jsPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const jsPlugin = {
transforms: [
{
test(id) {
return id.endsWith('testTransform.js')
},
transform(code) {
return code.replace(/__TEST_TRANSFORM__ = (\d)/, (matched, n) => {
return `__TEST_TRANSFORM__ = ${Number(n) + 1}`
})
}
}
]
}
19 changes: 19 additions & 0 deletions playground/plugins/sassPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import sass from 'sass'

export const sassPlugin = {
transforms: [
{
as: 'css',
test(id) {
return id.endsWith('.scss')
},
transform(code) {
return sass
.renderSync({
data: code
})
.css.toString()
}
}
]
}
1 change: 1 addition & 0 deletions playground/testTransform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const __TEST_TRANSFORM__ = 1
5 changes: 5 additions & 0 deletions playground/testTransform.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$color: cyan;

.transform-scss {
color: $color;
}
5 changes: 4 additions & 1 deletion playground/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { UserConfig } from 'vite'
import { sassPlugin } from './plugins/sassPlugin'
import { jsPlugin } from './plugins/jsPlugin'

const config: UserConfig = {
alias: {
Expand All @@ -8,7 +10,8 @@ const config: UserConfig = {
factory: 'h',
fragment: 'Fragment'
},
minify: false
minify: false,
plugins: [sassPlugin, jsPlugin]
}

export default config
27 changes: 24 additions & 3 deletions src/node/build/buildPluginCss.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import path from 'path'
import { Plugin } from 'rollup'
import { resolveAsset, registerAssets } from './buildPluginAsset'
import { isExternalUrl, asyncReplace, loadPostcssConfig } from '../utils'
import {
isExternalUrl,
asyncReplace,
loadPostcssConfig,
parseWithQuery
} from '../utils'
import { Transform } from '../config'

const debug = require('debug')('vite:build:css')

Expand All @@ -13,15 +19,30 @@ export const createBuildCssPlugin = (
assetsDir: string,
cssFileName: string,
minify: boolean,
inlineLimit: number
inlineLimit: number,
transforms: Transform[]
): Plugin => {
const styles: Map<string, string> = new Map()
const assets = new Map<string, Buffer>()
transforms = transforms.filter((t) => t.as === 'css')

return {
name: 'vite:css',
async transform(css: string, id: string) {
if (id.endsWith('.css')) {
let transformed = false

if (transforms.length) {
const { path, query } = parseWithQuery(id)
for (const t of transforms) {
if (t.test(path, query)) {
css = await t.transform(css, true)
transformed = true
break
}
}
}

if (transformed || id.endsWith('.css')) {
// process url() - register referenced files as assets
// and rewrite the url to the resolved public path
if (urlRE.test(css)) {
Expand Down
7 changes: 6 additions & 1 deletion src/node/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createEsbuildPlugin } from './buildPluginEsbuild'
import { createReplacePlugin } from './buildPluginReplace'
import { stopService } from '../esbuildService'
import { BuildConfig } from '../config'
import { createBuildJsTransformPlugin } from '../transform'

export interface BuildResult {
html: string
Expand Down Expand Up @@ -56,6 +57,7 @@ export async function build(options: BuildConfig = {}): Promise<BuildResult> {
assetsDir = 'assets',
assetsInlineLimit = 4096,
alias = {},
transforms = [],
resolvers = [],
vueCompilerOptions,
rollupInputOptions = {},
Expand Down Expand Up @@ -113,6 +115,8 @@ export async function build(options: BuildConfig = {}): Promise<BuildResult> {
compilerOptions: vueCompilerOptions
}),
require('@rollup/plugin-json')(),
// user transforms
...(transforms.length ? [createBuildJsTransformPlugin(transforms)] : []),
require('@rollup/plugin-node-resolve')({
rootDir: root,
extensions: supportedExts
Expand All @@ -135,7 +139,8 @@ export async function build(options: BuildConfig = {}): Promise<BuildResult> {
assetsDir,
cssFileName,
!!minify,
assetsInlineLimit
assetsInlineLimit,
transforms
),
// vite:asset
createBuildAssetPlugin(
Expand Down
6 changes: 3 additions & 3 deletions src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (argv.debug) {
import os from 'os'
import chalk from 'chalk'
import { Ora } from 'ora'
import { ServerConfig, BuildConfig, resolveConfig } from './config'
import { UserConfig, resolveConfig } from './config'

function logHelp() {
console.log(`
Expand Down Expand Up @@ -91,7 +91,7 @@ async function resolveOptions() {
}

async function runServe(
options: ServerConfig & {
options: UserConfig & {
port?: number
open?: boolean
}
Expand Down Expand Up @@ -141,7 +141,7 @@ async function runServe(
})
}

async function runBuild(options: BuildConfig) {
async function runBuild(options: UserConfig) {
let spinner: Ora | undefined
const msg = 'Building for production...'
if (process.env.DEBUG || process.env.NODE_ENV === 'test') {
Expand Down
22 changes: 7 additions & 15 deletions src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import Rollup, {
InputOptions as RollupInputOptions,
OutputOptions as RollupOutputOptions
} from 'rollup'
import { Transform } from './transform'

export { Resolver }
export { Resolver, Transform }

/**
* Options shared between server and build.
Expand Down Expand Up @@ -138,21 +139,8 @@ export interface BuildConfig extends SharedConfig {
}

export interface UserConfig extends BuildConfig {
configureServer?: ServerPlugin
plugins?: Plugin[]
}

export type Condition = RegExp | RegExp[] | (() => boolean)

export interface Transform {
include?: Condition
exclude?: Condition
query?: Condition
/**
* @default 'js'
*/
as?: 'js' | 'css'
transform?: (code: string) => string | Promise<string>
configureServer?: ServerPlugin
}

export interface Plugin
Expand Down Expand Up @@ -248,6 +236,9 @@ export async function resolveConfig(
for (const plugin of config.plugins) {
config = resolvePlugin(config, plugin)
}
// delete plugins so it doesn't get passed to `createServer` as server
// plugins.
delete config.plugins
}

require('debug')('vite:config')(
Expand Down Expand Up @@ -289,6 +280,7 @@ async function loadConfigFromBundledFile(

function resolvePlugin(config: UserConfig, plugin: Plugin): UserConfig {
return {
...config,
alias: {
...plugin.alias,
...config.alias
Expand Down
32 changes: 18 additions & 14 deletions src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { cssPlugin } from './serverPluginCss'
import { assetPathPlugin } from './serverPluginAssets'
import { esbuildPlugin } from './serverPluginEsbuild'
import { ServerConfig } from '../config'
import { createServerTransformPlugin } from '../transform'

export { rewriteImports } from './serverPluginModuleRewrite'

Expand All @@ -26,25 +27,15 @@ export interface ServerPluginContext {
config: ServerConfig
}

const internalPlugins: ServerPlugin[] = [
hmrPlugin,
moduleRewritePlugin,
moduleResolvePlugin,
vuePlugin,
esbuildPlugin,
jsonPlugin,
cssPlugin,
assetPathPlugin,
serveStaticPlugin
]

export function createServer(config: ServerConfig = {}): Server {
const {
root = process.cwd(),
plugins = [],
resolvers = [],
alias = {}
alias = {},
transforms = []
} = config

const app = new Koa()
const server = http.createServer(app.callback())
const watcher = chokidar.watch(root, {
Expand All @@ -60,7 +51,20 @@ export function createServer(config: ServerConfig = {}): Server {
config
}

;[...plugins, ...internalPlugins].forEach((m) => m(context))
const resolvedPlugins = [
...plugins,
hmrPlugin,
moduleRewritePlugin,
moduleResolvePlugin,
vuePlugin,
esbuildPlugin,
jsonPlugin,
cssPlugin,
assetPathPlugin,
...(transforms.length ? [createServerTransformPlugin(transforms)] : []),
serveStaticPlugin
]
resolvedPlugins.forEach((m) => m(context))

return server
}
17 changes: 14 additions & 3 deletions src/node/server/serverPluginCss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ interface ProcessedEntry {

const processedCSS = new Map<string, ProcessedEntry>()

export const cssPlugin: ServerPlugin = ({ root, app, watcher, resolver }) => {
export const cssPlugin: ServerPlugin = ({
root,
app,
watcher,
resolver,
config
}) => {
app.use(async (ctx, next) => {
await next()
// handle .css imports
if (
ctx.path.endsWith('.css') &&
ctx.response.is('css') &&
// note ctx.body could be null if upstream set status to 304
ctx.body
) {
Expand Down Expand Up @@ -46,14 +52,19 @@ export const cssPlugin: ServerPlugin = ({ root, app, watcher, resolver }) => {
if (!processedCSS.has(ctx.path)) {
await processCss(ctx)
}
ctx.type = 'css'
ctx.body = processedCSS.get(ctx.path)!.css
}
}
})

// handle hmr
const cssTransforms = config.transforms
? config.transforms.filter((t) => t.as === 'css')
: []

watcher.on('change', (file) => {
if (file.endsWith('.css')) {
if (file.endsWith('.css') || cssTransforms.some((t) => t.test(file, {}))) {
if (srcImportMap.has(file)) {
// this is a vue src import, skip
return
Expand Down
Loading

0 comments on commit 87ee998

Please sign in to comment.