Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rust plugin usage #1269

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/proud-snakes-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'create-farm-plugin': patch
'@farmfe/plugin-react': patch
'@farmfe/plugin-sass': patch
'@farmfe/core': patch
---

feat: normalize usage of rust plugins and js plugins
5 changes: 4 additions & 1 deletion crates/core/src/config/persistent_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ impl PersistentCacheConfig {
let mut content = String::new();

for dep in &cloned_obj.build_dependencies {
if !PathBuf::from(dep).exists() || !PathBuf::from(dep).is_file() {
if !PathBuf::from(dep).exists()
|| !PathBuf::from(dep).is_file()
|| dep.ends_with(".farm")
{
content.push_str(dep);
} else {
let c = std::fs::read_to_string(dep).unwrap();
Expand Down
1 change: 1 addition & 0 deletions examples/external/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@farmfe/cli": "^1.0.1",
"@farmfe/core": "^1.1.1",
"@types/jquery": "^3.5.29",
"jquery": "^3.7.1",
"typescript": "^5.4.3"
}
}
26 changes: 21 additions & 5 deletions examples/vite-adapter-react/farm.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import { defineConfig } from '@farmfe/core';
import Pages from 'vite-plugin-pages';
import react from '@farmfe/plugin-react';
import farmPluginHtmlTemplate from '@jstors/farm-plugin-html-template';
import path from 'path';

export default defineConfig({
plugins: ['@farmfe/plugin-react'],
vitePlugins:[
Pages({
resolver:'react'
}),
plugins: [
'@farmfe/plugin-react',
farmPluginHtmlTemplate({
template: path.resolve(__dirname, './index.html'),
data: { title: 'Farm React App' }
})
// [
// '@jstors/farm-plugin-html-template',
// {
// template: path.resolve(__dirname, './index.html'),
// data: { title: 'Farm React App' }
// }
// ]
],
vitePlugins: [
Pages({
resolver: 'react'
})
]
});
4 changes: 2 additions & 2 deletions examples/vite-adapter-react/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<title>${title}$</title>
</head>
<body>
<div id="root"></div>
<script src="./src/index.tsx"></script>
</body>
</html>
</html>
2 changes: 2 additions & 0 deletions examples/vite-adapter-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
"devDependencies": {
"@farmfe/cli": "workspace:*",
"@farmfe/core": "workspace:*",
"@jstors/farm-plugin-html-template": "^0.0.3",
"@farmfe/plugin-react": "^1.1.0",
"@types/react": "18",
"@types/react-dom": "18",
"farm-plugin-remove-console": "^0.1.4",
"react-refresh": "^0.14.0",
"vite-plugin-pages": "^0.32.0"
},
Expand Down
1 change: 1 addition & 0 deletions examples/vite-adapter-react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const container = document.querySelector('#root');
const root = createRoot(container);

function App() {
console.log('this is a react app');
return <Suspense fallback={<p>Loading...</p>}>{useRoutes(routes)}</Suspense>;
}

Expand Down
2 changes: 1 addition & 1 deletion js-plugins/dts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { JsPlugin } from '@farmfe/core';
import path from 'node:path';
import type { JsPlugin } from '@farmfe/core';

import Context from './context.js';
import { pluginName } from './options.js';
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export const CUSTOM_KEYS = {
external_record: 'external.record',
runtime_isolate: 'runtime.isolate'
};

export const FARM_RUST_PLUGIN_FUNCTION_ENTRY = 'func.js';
49 changes: 44 additions & 5 deletions packages/core/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import crypto from 'node:crypto';
import fs from 'node:fs';
import module from 'node:module';
import module, { createRequire } from 'node:module';
import path, { isAbsolute, join } from 'node:path';
import { pathToFileURL } from 'node:url';

import { PluginTransformHookParam, bindingPath } from '../../binding/index.js';
import {
PluginResolveHookParam,
PluginTransformHookParam,
bindingPath
} from '../../binding/index.js';
import { JsPlugin } from '../index.js';
import {
getSortedPlugins,
Expand Down Expand Up @@ -43,7 +46,8 @@ import merge from '../utils/merge.js';
import {
CUSTOM_KEYS,
DEFAULT_CONFIG_NAMES,
FARM_DEFAULT_NAMESPACE
FARM_DEFAULT_NAMESPACE,
FARM_RUST_PLUGIN_FUNCTION_ENTRY
} from './constants.js';
import { mergeConfig, mergeFarmCliConfig } from './mergeConfig.js';
import { normalizeExternal } from './normalize-config/normalize-external.js';
Expand Down Expand Up @@ -699,7 +703,10 @@ async function readConfigFile(

const compiler = new Compiler({
config: normalizedConfig,
jsPlugins: [replaceDirnamePlugin()],
jsPlugins: [
replaceDirnamePlugin(),
transformFarmPluginPath(configFilePath, inlineOptions.root)
],
rustPlugins: []
});

Expand Down Expand Up @@ -1029,3 +1036,35 @@ export function replaceDirnamePlugin() {
}
};
}

// try to transform rust plugin path to xxxx/func.js if this path is exists
const transformFarmPluginPath = (importers: string, root: string) => ({
name: 'transform-farm-plugin-path',
priority: 101,
resolve: {
filters: {
sources: ['^.*farm.*plugin.*$'],
importers: [importers]
},
executor: async (param: PluginResolveHookParam) => {
let pluginPath = param.source;
if (!path.isAbsolute(pluginPath) && !pluginPath.startsWith('.')) {
const require = createRequire(path.join(root, 'package.json'));
pluginPath = require.resolve(pluginPath);
const funcPluginPath = path.resolve(
pluginPath,
'..',
FARM_RUST_PLUGIN_FUNCTION_ENTRY
);
if (fs.existsSync(funcPluginPath)) {
return {
resolvedPath: funcPluginPath,
external: false,
sideEffects: false
};
}
}
return null;
}
}
});
29 changes: 23 additions & 6 deletions packages/core/src/plugin/rust/rustPluginResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@ export type RustPlugin =
| [
string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Record<string, any>
Record<string, any> | undefined
];

type RustPluginPathObject = {
binary: string;
options: Record<string, any>;
};

type RustPluginFunction = (
options?: Record<string, any>
) => [string, typeof options];
/**
* Resolve the binary plugin file, return [filePath, jsonStringifiedOptions]
* @param plugin rust plugin config
Expand All @@ -25,7 +33,7 @@ export async function rustPluginResolver(
options = '{}';
} else if (Array.isArray(plugin) && plugin.length === 2) {
pluginPath = plugin[0];
options = JSON.stringify(plugin[1]);
options = JSON.stringify(plugin[1]) ?? '{}';
} else {
throw new Error(
'Invalid config: [plugins]. A rust plugin must be a string, or [string, Record<string, any>]'
Expand All @@ -46,13 +54,22 @@ export async function rustPluginResolver(
} else {
pluginPath = await import(pluginPath).then((m) => m.default);
}
// console.log(pluginPath);

// Calling the plugin as a function
if (typeof pluginPath === 'function') {
const [_path, _options] = (pluginPath as RustPluginFunction)();
options = JSON.stringify({
..._options,
...JSON.parse(options)
});
pluginPath = _path;
}

// The entry js file should return { binary: string, options: Record<string, any> } when it's not string
if (typeof pluginPath !== 'string') {
const { binary, options: pluginOptions } = pluginPath as {
binary: string;
options: Record<string, any>;
};
const { binary, options: pluginOptions } =
pluginPath as RustPluginPathObject;
options = JSON.stringify({
...pluginOptions,
...JSON.parse(options)
Expand Down
4 changes: 2 additions & 2 deletions packages/core/tests/binding.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { test } from 'vitest';
import {
Compiler,
Logger,
UserConfig,
normalizeDevServerOptions,
normalizeUserCompilationConfig,
resolveMergedUserConfig,
UserConfig
resolveMergedUserConfig
} from '../src/index.js';

// just make sure the binding works
Expand Down
6 changes: 3 additions & 3 deletions packages/core/tests/common.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { fileURLToPath, pathToFileURL } from 'node:url';
import path from 'path';
import { Compiler } from '../src/compiler/index.js';
import { JsPlugin } from '../src/plugin/type.js';
import {
UserConfig,
normalizeUserCompilationConfig,
resolveMergedUserConfig,
UserConfig
resolveMergedUserConfig
} from '../src/config/index.js';
import { Logger } from '../src/index.js';
import { JsPlugin } from '../src/plugin/type.js';

export async function getCompiler(
root: string,
Expand Down
4 changes: 0 additions & 4 deletions packages/create-farm-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,6 @@ function replaceNamePlaceholders(
options: IResultType
): string {
const PLACEHOLDERS = [
{
name: '<FARM-RUST-PLUGIN-NPM-NAME>',
replace: () => options.pluginName
},
{
name: '<FARM-RUST-PLUGIN-NPM-NAME>',
replace: () => options.pluginName
Expand Down
3 changes: 3 additions & 0 deletions packages/create-farm-plugin/templates/rust/options.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IPluginOptions {

}
3 changes: 2 additions & 1 deletion packages/create-farm-plugin/templates/rust/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"prepublishOnly": "farm-plugin-tools prepublish"
},
"files": [
"scripts"
"scripts",
"options.d.ts"
]
}
3 changes: 3 additions & 0 deletions packages/create-farm-plugin/templates/rust/scripts/func.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import binPath from "./index.js";

export default (options)=>[binPath,options];
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
const binPath: string;
import type { IPluginOptions } from '../options.d';
declare const binPath: (options?: IPluginOptions) => [string, IPluginOptions];
export default binPath;