Skip to content

Commit

Permalink
feat: support customized config.server.hmr (fix #119)
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Mar 13, 2022
1 parent 2dd7406 commit c1bfa21
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 13 deletions.
7 changes: 5 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ module.exports = {
jest: true,
},
globals: {
page: 'readable',
globalThis: 'readable',
page: 'readonly',
globalThis: 'readonly',
__HMR_HOSTNAME__: 'readonly',
__HMR_PORT__: 'readonly',
__HMR_PROTOCOL__: 'readonly',
},
plugins: ['svelte3'],
overrides: [
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@types/prompts": "^2.0.13",
"@types/rimraf": "^3.0.0",
"@types/semver": "^7.3.6",
"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"chalk": "^4.1.1",
Expand Down Expand Up @@ -71,6 +72,7 @@
"typescript": "^4.2.2",
"vite": "^2.7.13",
"vite-plugin-checker": "workspace:*",
"ws": "^8.5.0",
"zx": "^1.14.2"
}
}
10 changes: 8 additions & 2 deletions packages/runtime/src/ws.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
const socketProtocol = null || (location.protocol === 'https:' ? 'wss' : 'ws')
const socketHost = `${location.hostname}:${location.port}`
// #region
// copied from https://github.dev/vitejs/vite/blob/76bbcd09985f85f7786b7e2e2d5ce177ee7d1916/packages/vite/src/client/client.ts#L25
// use server configuration, then fallback to inference
const socketProtocol = __HMR_PROTOCOL__ || (location.protocol === 'https:' ? 'wss' : 'ws')
const socketHost = __HMR_PORT__
? `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`
: `${__HMR_HOSTNAME__ || location.hostname}`
const socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr')
// #endregion

// #region
// NOTE: sync modification with packages/vite-plugin-checker/client/index.ts
Expand Down
52 changes: 49 additions & 3 deletions packages/vite-plugin-checker/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import chalk from 'chalk'
import { spawn } from 'child_process'
import pick from 'lodash.pick'
import npmRunPath from 'npm-run-path'
import { ConfigEnv, Plugin } from 'vite'
import path from 'path'
import { ConfigEnv, Plugin, ResolvedConfig } from 'vite'

import { Checker } from './Checker'
import {
RUNTIME_PUBLIC_PATH,
runtimeCode,
WS_CHECKER_RECONNECT_EVENT,
WS_CHECKER_CONFIG_RUNTIME_EVENT,
WS_CHECKER_RECONNECT_EVENT,
} from './client/index'
import {
ACTION_TYPES,
Expand All @@ -20,7 +22,6 @@ import {
SharedConfig,
UserPluginConfig,
} from './types'
import chalk from 'chalk'

export * from './types'
export * from './codeFrame'
Expand Down Expand Up @@ -53,6 +54,7 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin {
const overlayConfig = typeof userConfig?.overlay === 'object' ? userConfig?.overlay : null
let checkers: ServeAndBuildChecker[] = []
let viteMode: ConfigEnv['command'] | undefined
let resolvedConfig: ResolvedConfig | undefined

return {
name: 'vite-plugin-checker',
Expand All @@ -72,6 +74,9 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin {
})
})
},
configResolved(config) {
resolvedConfig = config
},
buildEnd() {
if (viteMode === 'serve') {
checkers.forEach((checker) => {
Expand All @@ -94,6 +99,43 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin {
}
}
},
transform(code, id) {
if (id === RUNTIME_PUBLIC_PATH) {
if (!resolvedConfig) return

// #region
// copied from https://github.dev/vitejs/vite/blob/76bbcd09985f85f7786b7e2e2d5ce177ee7d1916/packages/vite/src/client/client.ts#L25
let options = resolvedConfig.server.hmr
options = options && typeof options !== 'boolean' ? options : {}
const host = options.host || null
const protocol = options.protocol || null
let port: number | string | false | undefined
if (isObject(resolvedConfig.server.hmr)) {
port = resolvedConfig.server.hmr.clientPort || resolvedConfig.server.hmr.port
}
if (resolvedConfig.server.middlewareMode) {
port = String(port || 24678)
} else {
port = String(port || options.port || resolvedConfig.server.port!)
}

let hmrBase = resolvedConfig.base
if (options.path) {
hmrBase = path.posix.join(hmrBase, options.path)
}
if (hmrBase !== '/') {
port = path.posix.normalize(`${port}${hmrBase}`)
}

return code
.replace(/__HMR_PROTOCOL__/g, JSON.stringify(protocol))
.replace(/__HMR_HOSTNAME__/g, JSON.stringify(host))
.replace(/__HMR_PORT__/g, JSON.stringify(port))
// #endregion
}

return null
},
transformIndexHtml() {
if (viteMode === 'serve') {
return [
Expand Down Expand Up @@ -229,3 +271,7 @@ function spawnChecker(
})
})
}

export function isObject(value: unknown): value is Record<string, any> {
return Object.prototype.toString.call(value) === '[object Object]'
}
4 changes: 3 additions & 1 deletion playground/basic/__tests__/enableBuild-false.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ describe('enableBuild-false', () => {
})

it('test', async () => {
editFile('vite.config.ts', (code) => code.replace(`// edit-slot`, `enableBuild: false,`))
editFile('vite.config.ts', (code) =>
code.replace(`// checker-edit-slot`, `enableBuild: false,`)
)
await viteBuild({
unexpectedErrorMsg: 'error',
cwd: testDir,
Expand Down
61 changes: 61 additions & 0 deletions playground/basic/__tests__/hmr.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { killServer, preTest, viteServe } from 'vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox'
import {
editFile,
sleep,
testDir,
WORKER_CLEAN_TIMEOUT,
} from 'vite-plugin-checker/__tests__/e2e/testUtils'
import { WebSocketServer } from 'ws'

import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv'
import { serializers } from '../../../scripts/serializers'

expect.addSnapshotSerializer(serializers)

beforeAll(async () => {
await preTest()
})

afterAll(async () => {
await sleep(WORKER_CLEAN_TIMEOUT)
})

describe('hmr', () => {
beforeEach(async () => {
await copyCode()
})

afterEach(async () => {
await killServer()
})

it('hmr-config', async () => {
const port = 4567
const path = '/custom-path'

const hmrConfig = `
server: {
hmr: {
clientPort: ${port},
path: '${path}',
},
},`

editFile('vite.config.ts', (code) => code.replace('// config-edit-slot', hmrConfig))

const ws = new WebSocketServer({
port,
path,
})

const wsPromise = new Promise((resolve) => {
ws.on('connection', function connection(ws) {
resolve(undefined)
})
})

await viteServe({ cwd: testDir, launchPage: true })
await wsPromise
ws.close()
})
})
2 changes: 1 addition & 1 deletion playground/basic/__tests__/overlay-false.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('overlay-false', () => {
})

it('overlay: false', async () => {
editFile('vite.config.ts', (code) => code.replace('// edit-slot', 'overlay: false,'))
editFile('vite.config.ts', (code) => code.replace('// checker-edit-slot', 'overlay: false,'))

await viteServe({ cwd: testDir, launchPage: true })
await sleep(6000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('overlay-initialIsOpen-false', () => {

it('get initial error and subsequent error', async () => {
editFile('vite.config.ts', (code) =>
code.replace(`// edit-slot`, `overlay: { initialIsOpen: false },`)
code.replace(`// checker-edit-slot`, `overlay: { initialIsOpen: false },`)
)
await viteServe({
cwd: testDir,
Expand Down
2 changes: 1 addition & 1 deletion playground/basic/__tests__/overlay-position-style.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('overlay-position-style', () => {
it('get initial error and subsequent error', async () => {
editFile('vite.config.ts', (code) =>
code.replace(
`// edit-slot`,
`// checker-edit-slot`,
`overlay: { position: 'tr', badgeStyle: 'background-color: #E799B0', },`
)
)
Expand Down
2 changes: 1 addition & 1 deletion playground/basic/__tests__/overlay-terminal-false.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('overlay-terminal-false', () => {

it('get initial error and subsequent error', async () => {
let diagnostics: any
editFile('vite.config.ts', (code) => code.replace(`// edit-slot`, `terminal: false,`))
editFile('vite.config.ts', (code) => code.replace(`// checker-edit-slot`, `terminal: false,`))
await viteServe({
cwd: testDir,
wsSend: (_payload) => {
Expand Down
3 changes: 2 additions & 1 deletion playground/basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import checker from 'vite-plugin-checker'

// https://vitejs.dev/config/
export default defineConfig({
// config-edit-slot
plugins: [
checker({
eslint: {
lintCommand: 'eslint ./src --ext .ts',
},
// edit-slot
// checker-edit-slot
}),
],
})
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c1bfa21

Please sign in to comment.