Skip to content

Commit

Permalink
[Enhance] Modify to let the plugin do the build completion detection …
Browse files Browse the repository at this point in the history
…not file system. (#265)
  • Loading branch information
Jonghakseo authored Nov 11, 2023
1 parent 560c835 commit dbe8b00
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 75 deletions.
Empty file modified .husky/commit-msg
100644 → 100755
Empty file.
Empty file modified .husky/pre-commit
100644 → 100755
Empty file.
15 changes: 3 additions & 12 deletions utils/plugins/make-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import type { PluginOption } from 'vite';
const { resolve } = path;

const distDir = resolve(__dirname, '..', '..', 'dist');
const publicDir = resolve(__dirname, '..', '..', 'public');

export default function makeManifest(
manifest: chrome.runtime.ManifestV3,
config: { isDev: boolean; contentScriptCssKey?: string },
config: { contentScriptCssKey?: string },
): PluginOption {
function makeManifest(to: string) {
if (!fs.existsSync(to)) {
Expand All @@ -33,16 +32,8 @@ export default function makeManifest(

return {
name: 'make-manifest',
buildStart() {
if (config.isDev) {
makeManifest(distDir);
}
},
buildEnd() {
if (config.isDev) {
return;
}
makeManifest(publicDir);
writeBundle() {
makeManifest(distDir);
},
};
}
13 changes: 12 additions & 1 deletion utils/plugins/watch-rebuild.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import type { PluginOption } from 'vite';
import { resolve } from 'path';
import { WebSocket } from 'ws';
import MessageInterpreter from '../reload/interpreter';
import { LOCAL_RELOAD_SOCKET_URL } from '../reload/constant';

const rootDir = resolve(__dirname, '..', '..');
const manifestFile = resolve(rootDir, 'manifest.ts');
const viteConfigFile = resolve(rootDir, 'vite.config.ts');

export default function watchRebuild(): PluginOption {
const ws = new WebSocket(LOCAL_RELOAD_SOCKET_URL);
return {
name: 'watch-rebuild',
async buildStart() {
buildStart() {
this.addWatchFile(manifestFile);
this.addWatchFile(viteConfigFile);
},
writeBundle() {
/**
* When the build is complete, send a message to the reload server.
* The reload server will send a message to the client to reload or refresh the extension.
*/
ws.send(MessageInterpreter.send({ type: 'build_complete' }));
},
};
}
3 changes: 0 additions & 3 deletions utils/reload/constant.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
export const LOCAL_RELOAD_SOCKET_PORT = 8081;
export const LOCAL_RELOAD_SOCKET_URL = `ws://localhost:${LOCAL_RELOAD_SOCKET_PORT}`;
export const UPDATE_PENDING_MESSAGE = 'wait_update';
export const UPDATE_REQUEST_MESSAGE = 'do_update';
export const UPDATE_COMPLETE_MESSAGE = 'done_update';
18 changes: 8 additions & 10 deletions utils/reload/initReloadClient.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
LOCAL_RELOAD_SOCKET_URL,
UPDATE_COMPLETE_MESSAGE,
UPDATE_PENDING_MESSAGE,
UPDATE_REQUEST_MESSAGE,
} from './constant';
import { LOCAL_RELOAD_SOCKET_URL } from './constant';
import MessageInterpreter from './interpreter';

let needToUpdate = false;
Expand All @@ -18,22 +13,22 @@ export default function initReloadClient({
const socket = new WebSocket(LOCAL_RELOAD_SOCKET_URL);

function sendUpdateCompleteMessage() {
socket.send(MessageInterpreter.send({ type: UPDATE_COMPLETE_MESSAGE }));
socket.send(MessageInterpreter.send({ type: 'done_update' }));
}

socket.addEventListener('message', event => {
const message = MessageInterpreter.receive(String(event.data));

switch (message.type) {
case UPDATE_REQUEST_MESSAGE: {
case 'do_update': {
if (needToUpdate) {
sendUpdateCompleteMessage();
needToUpdate = false;
onUpdate();
}
return;
}
case UPDATE_PENDING_MESSAGE: {
case 'wait_update': {
if (!needToUpdate) {
needToUpdate = message.path.includes(watchPath);
}
Expand All @@ -43,9 +38,12 @@ export default function initReloadClient({
});

socket.onclose = () => {
console.warn(
console.log(
`Reload server disconnected.\nPlease check if the WebSocket server is running properly on ${LOCAL_RELOAD_SOCKET_URL}. This feature detects changes in the code and helps the browser to reload the extension or refresh the current tab.`,
);
setTimeout(() => {
initReloadClient({ watchPath, onUpdate });
}, 1000);
};

return socket;
Expand Down
46 changes: 12 additions & 34 deletions utils/reload/initReloadServer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { WebSocket, WebSocketServer } from 'ws';
import chokidar from 'chokidar';
import { debounce } from './utils';
import {
LOCAL_RELOAD_SOCKET_PORT,
LOCAL_RELOAD_SOCKET_URL,
UPDATE_COMPLETE_MESSAGE,
UPDATE_PENDING_MESSAGE,
UPDATE_REQUEST_MESSAGE,
} from './constant';
import { LOCAL_RELOAD_SOCKET_PORT, LOCAL_RELOAD_SOCKET_URL } from './constant';
import MessageInterpreter from './interpreter';
import { debounce } from './utils';

const clientsThatNeedToUpdate: Set<WebSocket> = new Set();

Expand All @@ -22,10 +16,16 @@ function initReloadServer() {

ws.addEventListener('close', () => clientsThatNeedToUpdate.delete(ws));
ws.addEventListener('message', event => {
const message = MessageInterpreter.receive(String(event.data));
if (message.type === UPDATE_COMPLETE_MESSAGE) {
if (typeof event.data !== 'string') return;

const message = MessageInterpreter.receive(event.data);

if (message.type === 'done_update') {
ws.close();
}
if (message.type === 'build_complete') {
clientsThatNeedToUpdate.forEach((ws: WebSocket) => ws.send(MessageInterpreter.send({ type: 'do_update' })));
}
});
});
}
Expand All @@ -35,31 +35,9 @@ const debounceSrc = debounce(function (path: string) {
// Normalize path on Windows
const pathConverted = path.replace(/\\/g, '/');
clientsThatNeedToUpdate.forEach((ws: WebSocket) =>
ws.send(
MessageInterpreter.send({
type: UPDATE_PENDING_MESSAGE,
path: pathConverted,
}),
),
ws.send(MessageInterpreter.send({ type: 'wait_update', path: pathConverted })),
);
// Delay waiting for public assets to be copied
}, 400);
chokidar.watch('src', { ignorePermissionErrors: true }).on('all', (_, path) => debounceSrc(path));

/** CHECK:: build was completed **/
const debounceDist = debounce(() => {
clientsThatNeedToUpdate.forEach((ws: WebSocket) => {
ws.send(MessageInterpreter.send({ type: UPDATE_REQUEST_MESSAGE }));
});
}, 100);
chokidar.watch('dist', { ignorePermissionErrors: true }).on('all', event => {
// Ignore unlink, unlinkDir and change events
// that happen in beginning of build:watch and
// that will cause ws.send() if it takes more than 400ms
// to build (which it might). This fixes:
// https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/issues/100
if (event !== 'add' && event !== 'addDir') return;
debounceDist();
});
chokidar.watch('src', { ignorePermissionErrors: true }).on('all', (_, path) => debounceSrc(path));

initReloadServer();
2 changes: 0 additions & 2 deletions utils/reload/injections/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ export default function addHmrIntoScript(watchPath: string) {
initReloadClient({
watchPath,
onUpdate: () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
chrome.runtime.reload();
},
});
Expand Down
6 changes: 3 additions & 3 deletions utils/reload/interpreter/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { ReloadMessage, SerializedMessage } from './types';
import type { WebSocketMessage, SerializedMessage } from './types';

export default class MessageInterpreter {
// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {}

static send(message: ReloadMessage): SerializedMessage {
static send(message: WebSocketMessage): SerializedMessage {
return JSON.stringify(message);
}
static receive(serializedMessage: SerializedMessage): ReloadMessage {
static receive(serializedMessage: SerializedMessage): WebSocketMessage {
return JSON.parse(serializedMessage);
}
}
17 changes: 9 additions & 8 deletions utils/reload/interpreter/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { UPDATE_COMPLETE_MESSAGE, UPDATE_PENDING_MESSAGE, UPDATE_REQUEST_MESSAGE } from '../constant';

type UpdatePendingMessage = {
type: typeof UPDATE_PENDING_MESSAGE;
type: 'wait_update';
path: string;
};

type UpdateRequestMessage = {
type: typeof UPDATE_REQUEST_MESSAGE;
type: 'do_update';
};

type UpdateCompleteMessage = { type: typeof UPDATE_COMPLETE_MESSAGE };
type UpdateCompleteMessage = { type: 'done_update' };
type BuildCompletionMessage = { type: 'build_complete' };

export type SerializedMessage = string;
export type ReloadMessage = UpdateCompleteMessage | UpdateRequestMessage | UpdatePendingMessage;
export type WebSocketMessage =
| UpdateCompleteMessage
| UpdateRequestMessage
| UpdatePendingMessage
| BuildCompletionMessage;
4 changes: 2 additions & 2 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ export default defineConfig({
plugins: [
react(),
makeManifest(manifest, {
isDev,
contentScriptCssKey: regenerateCacheInvalidationKey(),
}),
customDynamicImport(),
addHmr({ background: enableHmrInBackgroundScript, view: true }),
watchRebuild(),
isDev && watchRebuild(),
],
publicDir,
build: {
Expand All @@ -47,6 +46,7 @@ export default defineConfig({
minify: isProduction,
modulePreload: false,
reportCompressedSize: isProduction,
emptyOutDir: false,
rollupOptions: {
input: {
devtools: resolve(pagesDir, 'devtools', 'index.html'),
Expand Down

0 comments on commit dbe8b00

Please sign in to comment.