Socket
Socket
Sign inDemoInstall

vite

Package Overview
Dependencies
Maintainers
1
Versions
579
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vite - npm Package Compare versions

Comparing version 0.3.2 to 0.4.0

3

dist/client/client.d.ts
export declare function updateStyle(id: string, url: string): void;
export declare const hot: {
accept(importer: string, deps: string | string[], callback: (modules: object | object[]) => void): void;
};

39

dist/client/client.js

@@ -5,3 +5,3 @@ console.log('[vite] connecting...');

socket.addEventListener('message', ({ data }) => {
const { type, path, id, index } = JSON.parse(data);
const { type, path, id, index, timestamp } = JSON.parse(data);
switch (type) {

@@ -11,4 +11,4 @@ case 'connected':

break;
case 'reload':
import(`${path}?t=${Date.now()}`).then((m) => {
case 'vue-reload':
import(`${path}?t=${timestamp}`).then((m) => {
__VUE_HMR_RUNTIME__.reload(path, m.default);

@@ -18,4 +18,4 @@ console.log(`[vite] ${path} reloaded.`);

break;
case 'rerender':
import(`${path}?type=template&t=${Date.now()}`).then((m) => {
case 'vue-rerender':
import(`${path}?type=template&t=${timestamp}`).then((m) => {
__VUE_HMR_RUNTIME__.rerender(path, m.render);

@@ -25,7 +25,7 @@ console.log(`[vite] ${path} template updated.`);

break;
case 'style-update':
case 'vue-style-update':
updateStyle(id, `${path}?type=style&index=${index}&t=${timestamp}`);
console.log(`[vite] ${path} style${index > 0 ? `#${index}` : ``} updated.`);
updateStyle(id, `${path}?type=style&index=${index}&t=${Date.now()}`);
break;
case 'style-remove':
case 'vue-style-remove':
const link = document.getElementById(`vite-css-${id}`);

@@ -36,2 +36,12 @@ if (link) {

break;
case 'js-update':
const update = jsUpdateMap.get(path);
if (update) {
update(timestamp);
console.log(`[vite]: js module reloaded: `, path);
}
else {
console.error(`[vite] got js update notification but no client callback was registered. Something is wrong.`);
}
break;
case 'full-reload':

@@ -62,1 +72,14 @@ location.reload();

}
const jsUpdateMap = new Map();
export const hot = {
accept(importer, deps, callback) {
jsUpdateMap.set(importer, (timestamp) => {
if (Array.isArray(deps)) {
Promise.all(deps.map((dep) => import(dep + `?t=${timestamp}`))).then(callback);
}
else {
import(deps + `?t=${timestamp}`).then(callback);
}
});
}
};
import { Plugin } from '../index';
export declare const hmrClientPublicPath = "/@hmr";
export declare const hmrPlugin: Plugin;
"use strict";
// How HMR works
// 1. `.vue` files are transformed into `.js` files before being served
// 2. All `.js` files, before being served, are parsed to detect their imports
// (this is done in `./modules.ts`) for module import rewriting. During this
// we also record the importer/importee relationships which can beused for
// HMR analysis (we do both at the same time to avoid double parse costs)
// 3. When a `.vue` file changes, we directly read, parse it again and
// notify the client because Vue components are self-accepting by nature
// 4. When a js file changes, it triggers an HMR graph analysis, where we try to
// walk its importer chains and see if we reach a "HMR boundary". An HMR
// boundary is either a `.vue` file or a `.js` file that explicitly indicated
// that it accepts hot updates (by importing from the `/@hmr` special module)
// 5. If any parent chain exhausts without ever running into an HMR boundary,
// it's considered a "dead end". This causes a full page reload.
// 6. If a `.vue` boundary is encountered, we add it to the `vueImports` Set.
// 7. If a `.js` boundary is encountered, we check if the boundary's current
// child importer is in the accepted list of the boundary (see additional
// explanation below). If yes, record current child importer in the
// `jsImporters` Set.
// 8. If the graph walk finished without running into dead ends, notify the
// client to update all `jsImporters` and `vueImporters`.
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -12,10 +33,12 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const utils_1 = require("../utils");
const hmrClientPath = path_1.default.resolve(__dirname, '../../client/client.js');
const modules_1 = require("./modules");
const hmrClientFilePath = path_1.default.resolve(__dirname, '../../client/client.js');
exports.hmrClientPublicPath = '/@hmr';
exports.hmrPlugin = ({ root, app, server }) => {
app.use(async (ctx, next) => {
if (ctx.path !== '/__hmrClient') {
if (ctx.path !== exports.hmrClientPublicPath) {
return next();
}
ctx.type = 'js';
ctx.body = await utils_1.cachedRead(hmrClientPath);
ctx.body = await utils_1.cachedRead(hmrClientFilePath);
});

@@ -37,3 +60,7 @@ // start a websocket server to send hmr notifications to the client

});
const notify = (payload) => sockets.forEach((s) => s.send(JSON.stringify(payload)));
const notify = (payload) => {
const stringified = JSON.stringify(payload);
console.log(`[hmr] ${stringified}`);
sockets.forEach((s) => s.send(stringified));
};
const watcher = chokidar_1.default.watch(root, {

@@ -43,68 +70,127 @@ ignored: [/node_modules/]

watcher.on('change', async (file) => {
const resourcePath = '/' + path_1.default.relative(root, file);
const send = (payload) => {
console.log(`[hmr] ${JSON.stringify(payload)}`);
notify(payload);
};
const timestamp = Date.now();
const servedPath = '/' + path_1.default.relative(root, file);
if (file.endsWith('.vue')) {
const cacheEntry = vue_1.vueCache.get(file);
vue_1.vueCache.del(file);
const descriptor = await vue_1.parseSFC(root, file);
if (!descriptor) {
// read failed
return;
}
const prevDescriptor = cacheEntry && cacheEntry.descriptor;
if (!prevDescriptor) {
// the file has never been accessed yet
return;
}
// check which part of the file changed
if (!isEqual(descriptor.script, prevDescriptor.script)) {
send({
type: 'reload',
path: resourcePath
handleVueSFCReload(file, servedPath, timestamp);
}
else {
handleJSReload(servedPath, timestamp);
}
});
function handleJSReload(servedPath, timestamp) {
// normal js file
const importers = modules_1.importerMap.get(servedPath);
if (importers) {
const vueImporters = new Set();
const jsHotImporters = new Set();
const hasDeadEnd = walkImportChain(servedPath, importers, vueImporters, jsHotImporters);
if (hasDeadEnd) {
notify({
type: 'full-reload',
timestamp
});
return;
}
if (!isEqual(descriptor.template, prevDescriptor.template)) {
send({
type: 'rerender',
path: resourcePath
else {
vueImporters.forEach((vueImporter) => {
notify({
type: 'vue-reload',
path: vueImporter,
timestamp
});
});
return;
}
const prevStyles = prevDescriptor.styles || [];
const nextStyles = descriptor.styles || [];
if (prevStyles.some((s) => s.scoped) !== nextStyles.some((s) => s.scoped)) {
send({
type: 'reload',
path: resourcePath
jsHotImporters.forEach((jsImporter) => {
notify({
type: 'js-update',
path: jsImporter,
timestamp
});
});
}
const styleId = hash_sum_1.default(resourcePath);
nextStyles.forEach((_, i) => {
if (!prevStyles[i] || !isEqual(prevStyles[i], nextStyles[i])) {
send({
type: 'style-update',
path: resourcePath,
index: i,
id: `${styleId}-${i}`
});
}
}
function walkImportChain(importee, currentImporters, vueImporters, jsHotImporters) {
let hasDeadEnd = false;
for (const importer of currentImporters) {
if (importer.endsWith('.vue')) {
vueImporters.add(importer);
}
else if (isHMRBoundary(importer, importee)) {
jsHotImporters.add(importer);
}
else {
const parentImpoters = modules_1.importerMap.get(importer);
if (!parentImpoters) {
hasDeadEnd = true;
}
else {
hasDeadEnd = walkImportChain(importer, parentImpoters, vueImporters, jsHotImporters);
}
}
}
return hasDeadEnd;
}
function isHMRBoundary(importer, dep) {
const deps = modules_1.hmrBoundariesMap.get(importer);
return deps ? deps.has(dep) : false;
}
async function handleVueSFCReload(file, servedPath, timestamp) {
const cacheEntry = vue_1.vueCache.get(file);
vue_1.vueCache.del(file);
const descriptor = await vue_1.parseSFC(root, file);
if (!descriptor) {
// read failed
return;
}
const prevDescriptor = cacheEntry && cacheEntry.descriptor;
if (!prevDescriptor) {
// the file has never been accessed yet
return;
}
// check which part of the file changed
if (!isEqual(descriptor.script, prevDescriptor.script)) {
notify({
type: 'vue-reload',
path: servedPath,
timestamp
});
prevStyles.slice(nextStyles.length).forEach((_, i) => {
send({
type: 'style-remove',
path: resourcePath,
id: `${styleId}-${i + nextStyles.length}`
});
return;
}
if (!isEqual(descriptor.template, prevDescriptor.template)) {
notify({
type: 'vue-rerender',
path: servedPath,
timestamp
});
return;
}
else {
send({
type: 'full-reload'
const prevStyles = prevDescriptor.styles || [];
const nextStyles = descriptor.styles || [];
if (prevStyles.some((s) => s.scoped) !== nextStyles.some((s) => s.scoped)) {
notify({
type: 'vue-reload',
path: servedPath,
timestamp
});
}
});
const styleId = hash_sum_1.default(servedPath);
nextStyles.forEach((_, i) => {
if (!prevStyles[i] || !isEqual(prevStyles[i], nextStyles[i])) {
notify({
type: 'vue-style-update',
path: servedPath,
index: i,
id: `${styleId}-${i}`,
timestamp
});
}
});
prevStyles.slice(nextStyles.length).forEach((_, i) => {
notify({
type: 'vue-style-remove',
path: servedPath,
id: `${styleId}-${i + nextStyles.length}`,
timestamp
});
});
}
};

@@ -111,0 +197,0 @@ function isEqual(a, b) {

import { Plugin } from '../index';
export declare const modulesPlugin: Plugin;
declare type HMRStateMap = Map<string, Set<string>>;
export declare const importerMap: HMRStateMap;
export declare const importeeMap: HMRStateMap;
export declare const hmrBoundariesMap: HMRStateMap;
export {};

@@ -13,6 +13,10 @@ "use strict";

const utils_1 = require("../utils");
const fs_1 = require("fs");
const hmr_1 = require("./hmr");
const parser_1 = require("@babel/parser");
const idToFileMap = new Map();
const fileToIdMap = new Map();
const webModulesMap = new Map();
exports.modulesPlugin = ({ root, app }) => {
// rewrite named module imports to `/__modules/:id` requests
// rewrite named module imports to `/@modules/:id` requests
app.use(async (ctx, next) => {

@@ -27,19 +31,19 @@ await next();

ctx.body = html.replace(/(<script\b[^>]*>)([\s\S]*?)<\/script>/gm, (_, openTag, script) => {
return `${openTag}${rewriteImports(script)}</script>`;
return `${openTag}${rewriteImports(script, '/index.html')}</script>`;
});
}
// we are doing the js rewrite after all other middlewares have finished;
// this allows us to post-process javascript produced any user middlewares
// this allows us to post-process javascript produced by user middlewares
// regardless of the extension of the original files.
if (ctx.response.is('js') &&
// skip dependency modules
!ctx.path.startsWith(`/__`) &&
// skip special requests (internal scripts & module redirects)
!ctx.path.startsWith(`/@`) &&
// only need to rewrite for <script> part in vue files
!(ctx.path.endsWith('.vue') && ctx.query.type != null)) {
await es_module_lexer_1.init;
ctx.body = rewriteImports(await readBody(ctx.body));
ctx.body = rewriteImports(await readBody(ctx.body), ctx.url.replace(/(&|\?)t=\d+/, ''), ctx.query.t);
}
});
// handle /__modules/:id requests
const moduleRE = /^\/__modules\//;
// handle /@modules/:id requests
const moduleRE = /^\/@modules\//;
app.use(async (ctx, next) => {

@@ -68,3 +72,3 @@ if (!moduleRE.test(ctx.path)) {

const jsRequest = sourceMapRequest.replace(/\.map$/, '');
const moduleId = fileToIdMap.get(jsRequest);
const moduleId = fileToIdMap.get(path_1.default.basename(jsRequest));
if (!moduleId) {

@@ -78,3 +82,3 @@ console.error(`[vite] failed to infer original js file for source map request ` +

const modulePath = idToFileMap.get(moduleId);
const sourceMapPath = path_1.default.join(path_1.default.dirname(modulePath), sourceMapRequest);
const sourceMapPath = path_1.default.join(path_1.default.dirname(modulePath), path_1.default.basename(sourceMapRequest));
idToFileMap.set(sourceMapRequest, sourceMapPath);

@@ -86,8 +90,29 @@ ctx.type = 'application/json';

}
// TODO support resolving from Snowpack's web_modules
try {
const webModulePath = await resolveWebModule(root, id);
if (webModulePath) {
idToFileMap.set(id, webModulePath);
fileToIdMap.set(path_1.default.basename(webModulePath), id);
ctx.body = await utils_1.cachedRead(webModulePath);
return;
}
}
catch (e) {
console.error(e);
ctx.status = 404;
}
// resolve from node_modules
try {
const pkgPath = resolve_from_1.default(root, `${id}/package.json`);
// get the module name in case of deep imports like 'foo/dist/bar.js'
let moduleName = id;
const deepIndex = id.indexOf('/');
if (deepIndex > 0) {
moduleName = id.slice(0, deepIndex);
}
const pkgPath = resolve_from_1.default(root, `${moduleName}/package.json`);
const pkg = require(pkgPath);
const modulePath = path_1.default.join(path_1.default.dirname(pkgPath), pkg.module || pkg.main);
const moduleRelativePath = deepIndex > 0
? id.slice(deepIndex + 1)
: pkg.module || pkg.main || 'index.js';
const modulePath = path_1.default.join(path_1.default.dirname(pkgPath), moduleRelativePath);
idToFileMap.set(id, modulePath);

@@ -119,3 +144,29 @@ fileToIdMap.set(path_1.default.basename(modulePath), id);

}
function rewriteImports(source) {
async function resolveWebModule(root, id) {
const webModulePath = webModulesMap.get(id);
if (webModulePath) {
return webModulePath;
}
const importMapPath = path_1.default.join(root, 'web_modules', 'import-map.json');
if (await fs_1.promises.stat(importMapPath).catch((e) => false)) {
const importMap = require(importMapPath);
if (importMap.imports) {
const webModulesDir = path_1.default.dirname(importMapPath);
Object.entries(importMap.imports).forEach(([key, val]) => webModulesMap.set(key, path_1.default.join(webModulesDir, val)));
return webModulesMap.get(id);
}
}
}
exports.importerMap = new Map();
exports.importeeMap = new Map();
exports.hmrBoundariesMap = new Map();
const ensureMapEntry = (map, key) => {
let entry = map.get(key);
if (!entry) {
entry = new Set();
map.set(key, entry);
}
return entry;
};
function rewriteImports(source, importer, timestamp) {
try {

@@ -126,14 +177,50 @@ const [imports] = es_module_lexer_1.parse(source);

let hasReplaced = false;
const prevImportees = exports.importeeMap.get(importer);
const currentImportees = new Set();
exports.importeeMap.set(importer, currentImportees);
imports.forEach(({ s: start, e: end, d: dynamicIndex }) => {
const id = source.substring(start, end);
if (dynamicIndex < 0) {
if (dynamicIndex === -1) {
if (/^[^\/\.]/.test(id)) {
s.overwrite(start, end, `/__modules/${id}`);
s.overwrite(start, end, `/@modules/${id}`);
hasReplaced = true;
}
else if (id === hmr_1.hmrClientPublicPath) {
if (!/.vue$|.vue\?type=/.test(importer)) {
// the user explicit imports the HMR API in a js file
// making the module hot.
parseAcceptedDeps(source, importer, s);
// we rewrite the hot.accept call
hasReplaced = true;
}
}
else {
// force re-fetch all imports by appending timestamp
// if this is a hmr refresh request
if (timestamp) {
s.overwrite(start, end, `${id}${/\?/.test(id) ? `&` : `?`}t=${timestamp}`);
hasReplaced = true;
}
// save the import chain for hmr analysis
const importee = path_1.default.join(path_1.default.dirname(importer), id);
currentImportees.add(importee);
ensureMapEntry(exports.importerMap, importee).add(importer);
}
}
else {
else if (dynamicIndex >= 0) {
// TODO dynamic import
}
});
// since the importees may have changed due to edits,
// check if we need to remove this importer from certain importees
if (prevImportees) {
prevImportees.forEach((importee) => {
if (!currentImportees.has(importee)) {
const importers = exports.importerMap.get(importee);
if (importers) {
importers.delete(importer);
}
}
});
}
return hasReplaced ? s.toString() : source;

@@ -144,5 +231,54 @@ }

catch (e) {
console.error(`Error: module imports rewrite failed for source:\n`, source);
console.error(`[vite] Error: module imports rewrite failed for ${importer}.`, e);
return source;
}
}
function parseAcceptedDeps(source, importer, s) {
const ast = parser_1.parse(source, {
sourceType: 'module',
plugins: [
// by default we enable proposals slated for ES2020.
// full list at https://babeljs.io/docs/en/next/babel-parser#plugins
// this should be kept in async with @vue/compiler-core's support range
'bigInt',
'optionalChaining',
'nullishCoalescingOperator'
]
}).program.body;
const registerDep = (e) => {
const deps = ensureMapEntry(exports.hmrBoundariesMap, importer);
const depPublicPath = path_1.default.join(path_1.default.dirname(importer), e.value);
deps.add(depPublicPath);
s.overwrite(e.start, e.end, JSON.stringify(depPublicPath));
};
ast.forEach((node) => {
if (node.type === 'ExpressionStatement' &&
node.expression.type === 'CallExpression' &&
node.expression.callee.type === 'MemberExpression' &&
node.expression.callee.object.type === 'Identifier' &&
node.expression.callee.object.name === 'hot' &&
node.expression.callee.property.name === 'accept') {
const args = node.expression.arguments;
// inject the imports's own path so it becomes
// hot.accept('/foo.js', ['./bar.js'], () => {})
s.appendLeft(args[0].start, JSON.stringify(importer) + ', ');
// register the accepted deps
if (args[0].type === 'ArrayExpression') {
args[0].elements.forEach((e) => {
if (e && e.type !== 'StringLiteral') {
console.error(`[vite] HMR syntax error in ${importer}: hot.accept() deps list can only contain string literals.`);
}
else if (e) {
registerDep(e);
}
});
}
else if (args[0].type === 'StringLiteral') {
registerDep(args[0]);
}
else {
console.error(`[vite] HMR syntax error in ${importer}: hot.accept() expects a dep string or an array of deps.`);
}
}
});
}

@@ -11,2 +11,3 @@ "use strict";

const lru_cache_1 = __importDefault(require("lru-cache"));
const hmr_1 = require("./hmr");
exports.vueCache = new lru_cache_1.default({

@@ -41,3 +42,3 @@ max: 65535

ctx.type = 'css';
ctx.body = compileSFCStyle(root, descriptor.styles[index], index, filename, pathname);
ctx.body = await compileSFCStyle(root, descriptor.styles[index], index, filename, pathname);
return;

@@ -79,3 +80,3 @@ }

// inject hmr client
let code = `import { updateStyle } from "/__hmrClient"\n`;
let code = `import { updateStyle } from "${hmr_1.hmrClientPublicPath}"\n`;
if (descriptor.script) {

@@ -120,3 +121,3 @@ code += descriptor.script.content.replace(`export default`, 'const __script =');

scopeId: scoped ? `data-v-${hash_sum_1.default(pathname)}` : null,
runtimeModuleName: '/__modules/vue'
runtimeModuleName: '/@modules/vue'
}

@@ -132,3 +133,3 @@ });

}
function compileSFCStyle(root, style, index, filename, pathname) {
async function compileSFCStyle(root, style, index, filename, pathname) {
let cached = exports.vueCache.get(filename);

@@ -139,7 +140,9 @@ if (cached && cached.styles && cached.styles[index]) {

const id = hash_sum_1.default(pathname);
const { code, errors } = resolveVue_1.resolveCompiler(root).compileStyle({
const { code, errors } = await resolveVue_1.resolveCompiler(root).compileStyleAsync({
source: style.content,
filename,
id: `data-v-${id}`,
scoped: style.scoped != null
scoped: style.scoped != null,
preprocessLang: style.lang
// TODO load postcss config if present
});

@@ -146,0 +149,0 @@ // TODO css modules

{
"name": "vite",
"version": "0.3.2",
"version": "0.4.0",
"license": "MIT",

@@ -41,2 +41,3 @@ "author": "Evan You",

"dependencies": {
"@babel/parser": "^7.9.4",
"@types/koa": "^2.11.3",

@@ -43,0 +44,0 @@ "@vue/compiler-sfc": "^3.0.0-beta.3",

# vite
> No-bundle Dev Server for Vue Single-File Components
> No-bundle Dev Server for Vue 3 Single-File Components

@@ -14,6 +14,6 @@ **⚠️ Warning: Experimental ⚠️**

<script type="module">
import { createApp } from 'vue'
import Comp from './Comp.vue'
import { createApp } from 'vue'
import Comp from './Comp.vue'
createApp(Comp).mount('#app')
createApp(Comp).mount('#app')
</script>

@@ -36,3 +36,5 @@ ```

<style scoped>
button { color: red }
button {
color: red;
}
</style>

@@ -51,14 +53,132 @@ ```

- Imports are requested by the browser as native ES module imports - there's no bundling.
Imports are requested by the browser as native ES module imports - there's no bundling. The server intercepts requests to `*.vue` files, compiles them on the fly, and sends them back as JavaScript.
- The server intercepts requests to `*.vue` files, compiles them on the fly, and sends them back as JavaScript.
## Local Installation
- Imports to npm packages inside `.js` files (and in `<script>` of `index.html`) are re-written on the fly to point to locally installed files (only packages that provide ES module builds will work - `"module"` field will be used if present in `package.json`). There is also plans to integrate with [Snowpack](https://www.snowpack.dev/) to leverage its `web_modules`.
Alternatively, you can install `vite` locally as a dev dependency and run it via npm scripts:
- For libraries that provide ES modules builds that work in browsers, you can also directly import them from a CDN.
```bash
npm install -D vite
# OR
yarn add -D vite
```
Add scripts to `package.json` (here showing that serving the files in `src` instead of project root):
```json
{
"scripts": {
"dev": "vite --root src"
}
}
```
```bash
npm run dev
# OR
yarn dev
```
## Bare Module Resolving
Native ES imports doesn't support bare module imports like
```js
import { createApp } from 'vue'
```
The above will throw an error by default. `vite` detects such bare module imports in all served `.js` files and rewrite them with special paths like `/@modules/vue`. Under these special paths, `vite` performs module resolution to locate the correct files on disk:
- `vue` has special handling: you don't need to install it since `vite` will serve it by default. But if you want to use a specific version of `vue` (only supports Vue 3.x), you can install `vue` locally into `node_modules` and it will be preferred (`@vue/compiler-sfc` of the same version will also need to be installed).
- If a `web_modules` directory (generated by [Snowpack](https://www.snowpack.dev/))is present, we will try to locate the module it.
- Finally we will try resolving the module from `node_modules`, using the package's `module` entry if available.
## Hot Module Replacement
- `*.vue` files come with HMR out of the box.
- For `*.js` files, a simple HMR API is provided:
```js
import { foo } from './foo.js'
import { hot } from '/@hmr'
foo()
hot.accept('./foo.js', ({ foo }) => {
// the callback recevies the updated './foo.js' module
foo()
})
```
Note it's simplified and not fully compatible with webpack's HMR API, for example there is no self-accepting modules, and if you re-export `foo` from this file, it won't reflect changes in modules that import this file.
## CSS Pre-Processors
Install the corresponding pre-processor and just use it! (**Currently requires local installation of `vite` for correct resolution**).
``` bash
yarn add -D sass
```
``` vue
<style lang="scss">
/* use scss */
</style>
```
## API
You can customize the server using the API. The server can accept plugins which have access to the internal Koa app instance. You can then add custom Koa middlewares to add pre-processor support:
``` js
const { createServer } = require('vite')
const myPlugin = ({
root, // project root directory, absolute path
app, // Koa app instance
server // raw http server instance
}) => {
app.use(async (ctx, next) => {
// You can do pre-processing here - this will be the raw incoming requests
// before vite touches it.
if (ctx.path.endsWith('.scss')) {
// Note vue <style lang="xxx"> are supported by
// default as long as the corresponding pre-processor is installed, so this
// only applies to <link ref="stylesheet" href="*.scss"> or js imports like
// `import '*.scss'`.
console.log('pre processing: ', ctx.url)
ctx.type = 'css'
ctx.body = 'body { border: 1px solid red }'
}
// ...wait for vite to do built-in transforms
await next()
// Post processing before the content is served. Note this includes parts
// compiled from `*.vue` files, where <template> and <script> are served as
// `application/javascript` and <style> are served as `text/css`.
if (ctx.response.is('js')) {
console.log('post processing: ', ctx.url)
console.log(ctx.body) // can be string or Readable stream
}
})
}
createServer({
plugins: [
myPlugin
]
}).listen(3000)
```
## Deploying for Production
This project is highly experimental at this stage and is not production oriented. However, a valid Vite application can in theory be bundled with [Rollup](https://rollupjs.org/guide/en/) + [`rollup-plugin-vue@next`](https://github.com/vuejs/rollup-plugin-vue/tree/next) so it can be deployed as a static site.
## TODOs
- SourceMap
- Snowpack integration
- Custom imports map support
- Vue SFC Source Map support
- Custom imports map (alias) support
- Auto loading postcss config
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc