Skip to content

Commit

Permalink
chore: optimize cold start speed and fix lazy compilation issue (#70)
Browse files Browse the repository at this point in the history
* chore: add profiler and debug compilation slow issue on windows

* chore: optimize cold start speed

* chore: update lockfile
  • Loading branch information
wre232114 authored Mar 11, 2023
1 parent facaef3 commit b187971
Show file tree
Hide file tree
Showing 25 changed files with 553 additions and 63 deletions.
315 changes: 315 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions crates/compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::sync::Arc;
use farmfe_core::{
config::Config, context::CompilationContext, error::Result, plugin::Plugin, stats::Stats,
};
use farmfe_toolkit::tracing;
use update::{UpdateResult, UpdateType};

pub mod build;
Expand Down Expand Up @@ -51,6 +52,7 @@ impl Compiler {
}

/// Compile the project using the configuration
#[tracing::instrument(skip_all)]
pub fn compile(&self) -> Result<()> {
// triggering build stage
self.build()?;
Expand Down
12 changes: 12 additions & 0 deletions crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ farmfe_core = { path = "../core" }
farmfe_toolkit = { path = "../toolkit" }
regex = "1"
libloading = "0.7"
opentelemetry = { version = "0.18.0", default-features = false, features = [
"trace",
], optional = true }
tracing-opentelemetry = { version = "0.18.0", optional = true }
opentelemetry-jaeger = { version = "0.17.0", optional = true }

[features]
profiler = [
"dep:opentelemetry",
"dep:tracing-opentelemetry",
"dep:opentelemetry-jaeger",
]

[build-dependencies]
napi-build = "2.0.1"
Expand Down
49 changes: 40 additions & 9 deletions crates/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,32 @@ impl JsCompiler {
plugins_adapters.push(rust_plugin);
}

let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
#[cfg(not(feature = "profile"))]
{
let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();

tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.try_init()
.err();
}

tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.try_init()
.err();
#[cfg(feature = "profile")]
{
let tracer = opentelemetry_jaeger::new_agent_pipeline()
.with_service_name("farm_profile_pnpm")
.install_simple()
.unwrap();
let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);
tracing_subscriber::registry()
.with(opentelemetry)
.try_init()
.err();
}

Ok(Self {
compiler: Compiler::new(config, plugins_adapters)
Expand All @@ -116,6 +132,9 @@ impl JsCompiler {
.compile()
.map_err(|e| napi::Error::new(Status::GenericFailure, format!("{}", e)))?;

#[cfg(feature = "profile")]
opentelemetry::global::shutdown_tracer_provider();

Ok(())
}

Expand Down Expand Up @@ -207,6 +226,18 @@ impl JsCompiler {
result
}

#[napi]
pub fn relative_module_paths(&self) -> Vec<String> {
let context = self.compiler.context();
let module_graph = context.module_graph.read();

module_graph
.modules()
.into_iter()
.map(|m| m.id.relative_path().to_string())
.collect()
}

#[napi]
pub fn resource(&self, name: String) -> Option<Buffer> {
let context = self.compiler.context();
Expand Down
16 changes: 9 additions & 7 deletions crates/plugin_resolve/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::{collections::HashMap, path::Path, sync::Arc};
use std::{path::Path, sync::Arc};

use farmfe_core::{
config::Config,
context::CompilationContext,
error::Result,
plugin::{Plugin, PluginHookContext, PluginResolveHookParam, PluginResolveHookResult},
};
use farmfe_toolkit::tracing;
use farmfe_utils::parse_query;
use resolver::Resolver;

Expand All @@ -29,6 +30,7 @@ impl Plugin for FarmPluginResolve {
"FarmPluginResolve"
}

#[tracing::instrument(skip_all)]
fn resolve(
&self,
param: &PluginResolveHookParam,
Expand All @@ -40,7 +42,7 @@ impl Plugin for FarmPluginResolve {
// split query from source
let splits: Vec<&str> = source.split('?').collect();
let source = splits[0];

let basedir = if let Some(importer) = &param.importer {
if let Some(p) = Path::new(&importer.resolved_path(&context.config.root)).parent() {
p.to_path_buf()
Expand All @@ -62,10 +64,10 @@ impl Plugin for FarmPluginResolve {
}

let resolver = Resolver::new(context.config.resolve.clone());
Ok(resolver.resolve(source, basedir, &param.kind).map(|result| {
PluginResolveHookResult {
query,
..result
}}))
Ok(
resolver
.resolve(source, basedir.clone(), &param.kind)
.map(|result| PluginResolveHookResult { query, ..result }),
)
}
}
13 changes: 10 additions & 3 deletions crates/plugin_resolve/src/resolver.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::{
collections::HashMap,
path::{Path, PathBuf},
str::FromStr,
};
Expand All @@ -12,7 +11,10 @@ use farmfe_core::{
relative_path::RelativePath,
serde_json::{from_str, Map, Value},
};
use farmfe_toolkit::resolve::{follow_symlinks, load_package_json, package_json_loader::Options};
use farmfe_toolkit::{
resolve::{follow_symlinks, load_package_json, package_json_loader::Options},
tracing,
};

pub struct Resolver {
config: ResolveConfig,
Expand All @@ -33,6 +35,7 @@ impl Resolver {
/// * **exports**: refer to [exports](https://nodejs.org/api/packages.html#packages_conditional_exports), if source is end with '.js', also try to find '.ts' file
/// * **browser**: refer to [package-browser-field-spec](https://github.com/defunctzombie/package-browser-field-spec)
/// * **module/main**: `{ "module": "es/index.mjs", "main": "lib/index.cjs" }`
#[tracing::instrument(skip_all)]
pub fn resolve(
&self,
source: &str,
Expand Down Expand Up @@ -116,7 +119,8 @@ impl Resolver {
}
}

/// Try resolve as a file with the configured main fields.
/// Try resolve as a file with the configured main fields.
#[tracing::instrument(skip_all)]
fn try_directory(&self, dir: &PathBuf) -> Option<String> {
if !dir.is_dir() {
return None;
Expand All @@ -135,6 +139,7 @@ impl Resolver {

/// Try resolve as a file with the configured extensions.
/// If `/root/index` exists, return `/root/index`, otherwise try `/root/index.[configured extension]` in order, once any extension exists (like `/root/index.ts`), return it immediately
#[tracing::instrument(skip_all)]
fn try_file(&self, file: &PathBuf) -> Option<String> {
// TODO add a test that for directory imports like `import 'comps/button'` where comps/button is a dir
if file.exists() && file.is_file() {
Expand All @@ -157,6 +162,7 @@ impl Resolver {
}
}

#[tracing::instrument(skip_all)]
fn try_alias(
&self,
source: &str,
Expand All @@ -180,6 +186,7 @@ impl Resolver {
}

/// Resolve the source as a package
#[tracing::instrument(skip_all)]
fn try_node_modules(
&self,
source: &str,
Expand Down
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"loglevel",
"Pluggable",
"Rustup",
"clsx"
"clsx",
"opentelemetry"
],
"ignorePaths": [
"pnpm-lock.yaml",
Expand Down
9 changes: 9 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @farmfe/core

## 0.4.2

### Patch Changes

- limit the watched files to optimize cold start speed and fix lazy compilation issue"
- Updated dependencies
- @farmfe/runtime-plugin-hmr@3.0.5
- @farmfe/runtime@0.3.3

## 0.4.1

### Patch Changes
Expand Down
1 change: 1 addition & 0 deletions packages/core/binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ export class Compiler {
updateSync(paths: Array<string>): JsUpdateResult;
hasModule(resolvedPath: string): boolean;
resources(): Record<string, Buffer>;
relativeModulePaths(): Array<string>;
resource(name: string): Buffer | null;
}
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@farmfe/core",
"version": "0.4.1",
"version": "0.4.2",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
Expand Down Expand Up @@ -62,8 +62,8 @@
"type-check": "tsc -p tsconfig.build.json --noEmit"
},
"dependencies": {
"@farmfe/runtime": "workspace:^0.3.2",
"@farmfe/runtime-plugin-hmr": "workspace:^3.0.4",
"@farmfe/runtime": "workspace:^0.3.3",
"@farmfe/runtime-plugin-hmr": "workspace:^3.0.5",
"@swc/helpers": "^0.4.9",
"boxen": "^7.0.1",
"chalk": "^5.2.0",
Expand Down
17 changes: 17 additions & 0 deletions packages/core/src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import path from 'node:path';
import type { Config, JsUpdateResult } from '../../binding/index.js';
import { Compiler as BindingCompiler } from '../../binding/index.js';

export const VIRTUAL_FARM_DYNAMIC_IMPORT_PREFIX =
'virtual:FARMFE_DYNAMIC_IMPORT:';

export class Compiler {
private _bindingCompiler: BindingCompiler;

Expand Down Expand Up @@ -85,4 +88,18 @@ export class Compiler {
rmSync(outputPath, { recursive: true });
}
}

resolvedModulePaths(root: string): string[] {
return this._bindingCompiler
.relativeModulePaths()
.map((p) => this.transformModulePath(root, p));
}

transformModulePath(root: string, p: string): string {
if (p.startsWith(VIRTUAL_FARM_DYNAMIC_IMPORT_PREFIX)) {
return p.slice(VIRTUAL_FARM_DYNAMIC_IMPORT_PREFIX.length);
}

return path.join(root, p);
}
}
20 changes: 17 additions & 3 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,24 @@ export async function start(options: {
const compiler = new Compiler(normalizedConfig);
const devServer = new DevServer(compiler, logger, userConfig.server);

await devServer.listen();
// Make sure the server is listening before we watch for file changes
if (devServer.config.hmr) {
logger.info(
'HMR enabled, watching for file changes under ' +
chalk.green(userConfig.root)
);

if (normalizedConfig.config.mode === 'production') {
logger.error(
'HMR can not be enabled in production mode. Please set the mode option to "development" in your config file.'
);
process.exit(1);
}

const fileWatcher = new FileWatcher(userConfig.root, devServer.config.hmr);
fileWatcher.watch(devServer);
}

devServer.listen();
}

export async function build(options: {
Expand All @@ -60,5 +68,11 @@ export async function build(options: {
compiler.removeOutputPathDir();
await compiler.compile();
compiler.writeResourcesToDisk();
logger.info(`Build completed in ${chalk.green(`${Date.now() - start}ms`)}!`);
logger.info(
`Build completed in ${chalk.green(
`${Date.now() - start}ms`
)}! Resources emitted to ${chalk.green(
normalizedConfig.config.output.path
)}.`
);
}
2 changes: 1 addition & 1 deletion packages/core/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ export class DefaultLogger implements Logger {
}

error(message: string): void {
log.error(message);
log.error(chalk.red(message));
}
}
Loading

0 comments on commit b187971

Please sign in to comment.