Skip to content

Commit

Permalink
feat: new cli plugin (#6488)
Browse files Browse the repository at this point in the history
  • Loading branch information
caohuilin authored Nov 25, 2024
1 parent f5f73a7 commit ccedaab
Show file tree
Hide file tree
Showing 59 changed files with 2,972 additions and 291 deletions.
8 changes: 8 additions & 0 deletions .changeset/stupid-masks-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@modern-js/app-tools': minor
'@modern-js/plugin-v2': minor
---

feat: new cli plugin

feat: 新版 CLI 插件
4 changes: 2 additions & 2 deletions packages/solutions/app-tools/bin/modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ if (!process.env.MODERN_JS_VERSION) {
process.env.MODERN_JS_VERSION = version;
}

require('@modern-js/core/runBin').run({
require('../dist/cjs/new/run.js').run({
internalPlugins: {
cli: INTERNAL_APP_TOOLS_PLUGINS,
autoLoad: INTERNAL_APP_TOOLS_RUNTIME_PLUGINS,
},
initialLog: `Modern.js Framework v${version}`,
version,
});
9 changes: 9 additions & 0 deletions packages/solutions/app-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"jsnext:source": "./src/index.ts",
"default": "./dist/cjs/index.js"
},
"./cli/run": {
"types": "./dist/types/new/run.d.ts",
"jsnext:source": "./src/new/run.ts",
"default": "./dist/cjs/new/run.js"
},
"./types": {
"types": "./lib/types.d.ts",
"jsnext:source": "./lib/types.d.ts",
Expand All @@ -58,6 +63,9 @@
".": [
"./dist/types/index.d.ts"
],
"cli/run": [
"./dist/types/new/run.d.ts"
],
"types": [
"./lib/types.d.ts"
],
Expand All @@ -84,6 +92,7 @@
"@babel/parser": "^7.22.15",
"@babel/traverse": "^7.23.2",
"@babel/types": "^7.26.0",
"@modern-js/plugin-v2": "workspace:*",
"@modern-js/core": "workspace:*",
"@modern-js/node-bundle-require": "workspace:*",
"@modern-js/plugin": "workspace:*",
Expand Down
186 changes: 3 additions & 183 deletions packages/solutions/app-tools/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,193 +1,13 @@
import path from 'path';
import type { CliPlugin } from '@modern-js/core';
import { getLocaleLanguage } from '@modern-js/plugin-i18n/language-detector';
import { castArray } from '@modern-js/uni-builder';
import {
cleanRequireCache,
deprecatedCommands,
emptyDir,
getArgv,
getCommand,
} from '@modern-js/utils';
import { hooks } from './hooks';
import { i18n } from './locale';
import analyzePlugin from './plugins/analyze';
import deployPlugin from './plugins/deploy';
import initializePlugin from './plugins/initialize';
import serverBuildPlugin from './plugins/serverBuild';
import type { AppTools } from './types';

import {
buildCommand,
deployCommand,
devCommand,
inspectCommand,
newCommand,
serverCommand,
upgradeCommand,
} from './commands';
import { generateWatchFiles } from './utils/generateWatchFiles';
import { restart } from './utils/restart';
import { appTools } from './new/index';

export { appTools, initAppContext, type AppToolsPlugin } from './new/index';
export { dev } from './commands/dev';
export type { DevOptions } from './utils/types';

export { mergeConfig } from '@modern-js/core';
export * from './defineConfig';
export { defineConfig, defineLegacyConfig } from './defineConfig';
export * from './types';

export type { RuntimeUserConfig } from './types/config';

export type AppToolsOptions = {
/**
* Specify which bundler to use for the build.
* @default `webpack`
* */
bundler?: 'rspack' | 'webpack' | 'experimental-rspack';
};
/**
* The core package of the framework, providing CLI commands, build capabilities, configuration parsing and more.
*/
export const appTools = (
options: AppToolsOptions = {
// default webpack to be compatible with original projects
bundler: 'webpack',
},
): CliPlugin<AppTools<'shared'>> => ({
name: '@modern-js/app-tools',

post: [
'@modern-js/plugin-initialize',
'@modern-js/plugin-analyze',
'@modern-js/plugin-ssr',
'@modern-js/plugin-document',
'@modern-js/plugin-state',
'@modern-js/plugin-router',
'@modern-js/plugin-router-v5',
'@modern-js/plugin-polyfill',
],

registerHook: hooks,

usePlugins: [
initializePlugin({
bundler:
options?.bundler &&
['rspack', 'experimental-rspack'].includes(options.bundler)
? 'rspack'
: 'webpack',
}),
analyzePlugin({
bundler:
options?.bundler &&
['rspack', 'experimental-rspack'].includes(options.bundler)
? 'rspack'
: 'webpack',
}),
serverBuildPlugin(),
deployPlugin(),
],

setup: api => {
const appContext = api.useAppContext();
api.setAppContext({
...appContext,
toolsType: 'app-tools',
});

const locale = getLocaleLanguage();
i18n.changeLanguage({ locale });

return {
async beforeConfig() {
const userConfig = api.useConfigContext();
const appContext = api.useAppContext();
if (userConfig.output?.tempDir) {
api.setAppContext({
...appContext,
internalDirectory: path.resolve(
appContext.appDirectory,
userConfig.output.tempDir,
),
});
}
},
async commands({ program }) {
await devCommand(program, api);
await buildCommand(program, api);
serverCommand(program, api);
deployCommand(program, api);
newCommand(program, locale);
inspectCommand(program, api);
upgradeCommand(program);
deprecatedCommands(program);
},

async prepare() {
const command = getCommand();
if (command === 'deploy') {
const isSkipBuild = ['-s', '--skip-build'].some(tag => {
return getArgv().includes(tag);
});
// if skip build, do not clean dist path
if (isSkipBuild) {
return;
}
}

// clean dist path before building
if (
command === 'dev' ||
command === 'start' ||
command === 'build' ||
command === 'deploy'
) {
const resolvedConfig = api.useResolvedConfigContext();
if (resolvedConfig.output.cleanDistPath) {
const appContext = api.useAppContext();
await emptyDir(appContext.distDirectory);
}
}
},

async watchFiles() {
const appContext = api.useAppContext();
const config = api.useResolvedConfigContext();
const files = await generateWatchFiles(
appContext,
config.source.configDir,
);

const watchFiles = castArray(config.dev.watchFiles);
watchFiles.forEach(({ type, paths }) => {
if (type === 'reload-server') {
files.push(...(Array.isArray(paths) ? paths : [paths]));
}
});

return files;
},

// 这里会被 core/initWatcher 监听的文件变动触发,如果是 src 目录下的文件变动,则不做 restart
async fileChange(e: {
filename: string;
eventType: string;
isPrivate: boolean;
}) {
const { filename, eventType, isPrivate } = e;

if (!isPrivate && (eventType === 'change' || eventType === 'unlink')) {
const { closeServer } = await import('./utils/createServer.js');
await closeServer();
await restart(api.useHookRunners(), filename);
}
},

async beforeRestart() {
cleanRequireCache([require.resolve('./plugins/analyze')]);
},
};
},
});

export default appTools;
Loading

0 comments on commit ccedaab

Please sign in to comment.