Skip to content

Commit

Permalink
feat: restart server when svelte config file changes (fixes #63) (#72)
Browse files Browse the repository at this point in the history
* feat: restart server when svelte config file changes (fixes #63)

* fix: make sure the absolute path of the loaded svelte config file is kept in resolvedOptions

* refactor: use package.json scripts and execa to start servers for e2e-tests; add tests for svelte config watching

* fix: remove syntax not supported by node12 from e2e script

* fix: use writeFileSync instead of fs/promises for node12

* chore: remove debugging screenshots

* chore: update dependencies

* test: move to lower portrange and archive dist on failure

* test: fix e2e-server script. correct error output and don't throw if closing server wasn't graceful

* fix: really bad c&p err

* test: increase sleep time on windows to account for slower devserver restart

* fix invalid doc

* chore: update changeset
  • Loading branch information
dominikg authored Jun 30, 2021
1 parent 97ee68c commit 5100376
Show file tree
Hide file tree
Showing 42 changed files with 1,059 additions and 850 deletions.
7 changes: 7 additions & 0 deletions .changeset/large-ears-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@sveltejs/vite-plugin-svelte': minor
---

- Restart dev server when svelte config file changes
- Refactored e2e-tests to use package.json scripts
- Updated dependencies
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
- name: archive tests temp directory
if: failure()
shell: bash
run: tar -cvf test-temp.tar --exclude="node_modules" --exclude=".yarn" --exclude="dist" --exclude=".pnp.js" temp/
run: tar -cvf test-temp.tar --exclude="node_modules" temp/
- uses: actions/upload-artifact@v2
if: failure()
with:
Expand Down
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"build": "pnpm --dir packages/vite-plugin-svelte build",
"test": "run-s test:serve test:build",
"test:serve": "jest",
"test:serve:debug": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/jest",
"test:serve:debug": "cross-env DEBUG=pw:api VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/jest/bin/jest --runInBand",
"test:build": "cross-env VITE_TEST_BUILD=1 jest",
"test:build:debug": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 node --inspect-brk ./node_modules/.bin/jest",
"test:build:debug": "cross-env DEBUG=pw:api VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 node --inspect-brk ./node_modules/jest/bin/jest --runInBand",
"test:ci": "run-s test:ci:serve test:ci:build",
"test:ci:serve": "cross-env VITE_PRESERVE_BUILD_ARTIFACTS=1 jest --verbose --no-cache --runInBand --force-exit --ci --json --outputFile=\"temp/serve/jest-results.json\"",
"test:ci:build": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 jest --verbose --no-cache --runInBand --force-exit --ci --json --outputFile=\"temp/build/jest-results.json\"",
Expand All @@ -27,14 +27,14 @@
"@changesets/cli": "^2.16.0",
"@types/fs-extra": "^9.0.11",
"@types/jest": "^26.0.23",
"@types/node": "^15.12.4",
"@types/node": "^15.12.5",
"@types/semver": "^7.3.6",
"@typescript-eslint/eslint-plugin": "^4.28.0",
"@typescript-eslint/parser": "^4.28.0",
"@typescript-eslint/eslint-plugin": "^4.28.1",
"@typescript-eslint/parser": "^4.28.1",
"chalk": "^4.1.1",
"cross-env": "^7.0.3",
"enquirer": "^2.3.6",
"esbuild": "^0.12.9",
"esbuild": "^0.12.12",
"eslint": "^7.29.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-html": "^6.1.2",
Expand All @@ -46,22 +46,22 @@
"execa": "^5.1.1",
"fs-extra": "^10.0.0",
"husky": "^6.0.0",
"jest": "^27.0.5",
"jest-environment-node": "^27.0.5",
"jest": "^27.0.6",
"jest-environment-node": "^27.0.6",
"jest-junit": "^12.2.0",
"lint-staged": "^11.0.0",
"minimist": "^1.2.5",
"node-fetch": "^2.6.1",
"npm-check-updates": "^11.7.1",
"npm-run-all": "^4.1.5",
"playwright-core": "^1.12.2",
"pnpm": "^6.8.0",
"prettier": "^2.3.1",
"playwright-core": "^1.12.3",
"pnpm": "^6.9.1",
"prettier": "^2.3.2",
"prettier-plugin-svelte": "^2.3.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"sirv": "^1.0.12",
"svelte": "^3.38.2",
"svelte": "^3.38.3",
"ts-jest": "^27.0.3",
"typescript": "^4.3.4",
"vite": "^2.3.8"
Expand Down
11 changes: 6 additions & 5 deletions packages/e2e-tests/autoprefixer-browerslist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"dev": "vite"
"preview": "vite preview"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "workspace:*",
"autoprefixer": "^10.2.6",
"postcss": "^8.3.5",
"postcss-load-config": "^3.1.0",
"svelte": "^3.38.2",
"svelte": "^3.38.3",
"svelte-hmr": "^0.14.4",
"svelte-preprocess": "^4.7.3",
"vite": "^2.3.8"
Expand Down
15 changes: 12 additions & 3 deletions packages/e2e-tests/autoprefixer-browerslist/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
const { svelte } = require('@sveltejs/vite-plugin-svelte');
const { defineConfig } = require('vite');

module.exports = defineConfig(({ command, mode }) => {
const isProduction = mode === 'production';
module.exports = defineConfig(() => {
return {
plugins: [svelte()],
build: {
minify: isProduction
// make build faster by skipping transforms and minification
target: 'esnext',
minify: false
},
server: {
watch: {
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100
}
}
};
});
12 changes: 6 additions & 6 deletions packages/e2e-tests/configfile-custom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"dev": "vite"
"preview": "vite preview"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "workspace:*",
"svelte": "^3.38.2",
"svelte": "^3.38.3",
"svelte-hmr": "^0.14.4",
"svelte-preprocess": "^4.7.3",
"vite": "^2.3.8"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const sveltePreprocess = require('svelte-preprocess');

module.exports = {
preprocess: sveltePreprocess()
emitCss: false
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
/*
const sveltePreprocess = require('svelte-preprocess');
module.exports = {
preprocess: sveltePreprocess()
};
*/
export default {
emitCss: true
emitCss: false
}
15 changes: 12 additions & 3 deletions packages/e2e-tests/configfile-custom/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
const { svelte } = require('@sveltejs/vite-plugin-svelte');
const { defineConfig } = require('vite');

module.exports = defineConfig(({ command, mode }) => {
const isProduction = mode === 'production';
module.exports = defineConfig(() => {
return {
plugins: [svelte({ configFile: 'svelte.config.custom.cjs' })],
build: {
minify: isProduction
// make build faster by skipping transforms and minification
target: 'esnext',
minify: false
},
server: {
watch: {
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100
}
}
};
});
13 changes: 7 additions & 6 deletions packages/e2e-tests/configfile-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"dev": "vite"
"preview": "vite preview"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"dependencies": {
"e2e-tests-hmr-test-dependency": "workspace:*"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "workspace:*",
"svelte": "^3.38.2",
"svelte": "^3.38.3",
"svelte-hmr": "^0.14.4",
"svelte-preprocess": "^4.7.3",
"vite": "^2.3.8"
},
"type": "module"
"type": "module"
}
13 changes: 11 additions & 2 deletions packages/e2e-tests/configfile-esm/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
import { defineConfig } from 'vite';

export default defineConfig(({ command, mode }) => {
const isProduction = mode === 'production';
return {
plugins: [svelte()],
build: {
minify: isProduction
// make build faster by skipping transforms and minification
target: 'esnext',
minify: false
},
server: {
watch: {
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100
}
}
};
});
151 changes: 151 additions & 0 deletions packages/e2e-tests/e2e-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// script to start package.json dev/build/preview scripts with execa for e2e tests
const execa = require('execa');
const treeKill = require('tree-kill');
const fs = require('fs');
const path = require('path');
const isWin = process.platform === 'win32';
async function startedOnPort(serverProcess, port, timeout) {
let id;
let stdoutListener;
const timerPromise = new Promise(
(_, reject) =>
(id = setTimeout(() => {
reject(`timeout for server start after ${timeout}`);
}, timeout))
);
const startedPromise = new Promise((resolve, reject) => {
stdoutListener = (data) => {
const str = data.toString();
// hack, console output may contain color code gibberish
// skip gibberish between localhost: and port number
const match = str.match(/(http:\/\/localhost:)(?:.*)(\d{4})/);
if (match) {
const startedPort = parseInt(match[2], 10);
if (startedPort === port) {
resolve();
} else {
const msg = `test server started on ${startedPort} instead of ${port}`;
console.log(msg);
reject(msg);
}
}
};

serverProcess.stdout.on('data', stdoutListener);
});

return Promise.race([timerPromise, startedPromise]).finally(() => {
serverProcess.stdout.off('data', stdoutListener);
clearTimeout(id);
});
}

exports.serve = async function serve(root, isBuild, port) {
const logDir = path.join(root, 'logs');
const logs = {
server: null,
build: null
};
const writeLogs = async (name, result) => {
try {
if (result.out && result.out.length > 0) {
fs.writeFileSync(path.join(logDir, `${name}.log`), result.out.join(''), 'utf-8');
}
if (result.err && result.err.length > 0) {
fs.writeFileSync(path.join(logDir, `${name}.err.log`), result.err.join(''), 'utf-8');
}
} catch (e1) {
console.error(`failed to write ${name} logs in ${logDir}`, e1);
}
};

if (isBuild) {
let buildResult;
let hasErr = false;
let out = [];
let err = [];

try {
const buildProcess = execa('pnpm', ['build'], {
preferLocal: true,
cwd: root,
stdio: 'pipe'
});
logs.build = { out, err };
buildProcess.stdout.on('data', (d) => out.push(d.toString()));
buildProcess.stderr.on('data', (d) => err.push(d.toString()));
await buildProcess;
} catch (e) {
buildResult = e;
if (buildResult.stdout) {
out.push(buildResult.stdout);
}
if (buildResult.stderr) {
err.push(buildResult.stderr);
}
hasErr = true;
}
await writeLogs('build', logs.build);
if (hasErr) {
throw buildResult;
}
}

const serverProcess = execa('pnpm', [isBuild ? 'preview' : 'dev', '--', '--port', port], {
preferLocal: true,
cwd: root,
stdio: 'pipe'
});
const out = [],
err = [];
logs.server = { out, err };
serverProcess.stdout.on('data', (d) => out.push(d.toString()));
serverProcess.stderr.on('data', (d) => err.push(d.toString()));

const closeServer = async () => {
if (serverProcess) {
if (serverProcess.pid) {
await new Promise((resolve) => {
treeKill(serverProcess.pid, (err) => {
if (err) {
console.error(`failed to treekill serverprocess ${serverProcess.pid}`, err);
}
resolve();
});
});
} else {
serverProcess.cancel();
}

try {
await serverProcess;
} catch (e) {
if (e.stdout) {
out.push(e.stdout);
}
if (e.stderr) {
err.push(e.stderr);
}
if (!isWin) {
// treekill on windows uses taskkill and that ends up here always
console.error(`server process did not exit gracefully. dir: ${root}`, e);
}
}
}
await writeLogs('server', logs.server);
};
try {
await startedOnPort(serverProcess, port, 20000);
return {
port,
logs,
close: closeServer
};
} catch (e) {
try {
await closeServer();
} catch (e1) {
console.error('failed to close server process', e1);
}
}
};
Loading

0 comments on commit 5100376

Please sign in to comment.