jsx/solid bundle

This commit is contained in:
Robin Appelman 2023-04-10 18:57:46 +02:00
commit 10ea8ddcbc
16 changed files with 458 additions and 44 deletions

View file

@ -1,12 +1,15 @@
use anyhow::Error;
use jsx_dom_expressions::TransformVisitor;
use std::collections::HashMap;
use std::io::Write;
use std::sync::Arc;
use swc_atoms::js_word;
use swc_bundler::{Bundler, Load, ModuleData, ModuleRecord};
use swc_common::comments::NoopComments;
use swc_common::sync::Lrc;
use swc_common::{
errors::{ColorConfig, Handler},
FileName, SourceMap, Span, GLOBALS,
FileName, Mark, SourceMap, Span, GLOBALS,
};
use swc_ecma_ast::*;
use swc_ecma_codegen::text_writer::{omit_trailing_semi, JsWriter, WriteJs};
@ -14,24 +17,35 @@ use swc_ecma_codegen::Emitter;
use swc_ecma_loader::resolvers::lru::CachingResolver;
use swc_ecma_loader::resolvers::node::NodeModulesResolver;
use swc_ecma_loader::TargetEnv;
use swc_ecma_parser::{parse_file_as_module, Syntax};
use swc_ecma_parser::{parse_file_as_module, Syntax, TsConfig};
use swc_ecma_transforms_base::fixer::fixer;
use swc_ecma_transforms_base::hygiene::hygiene;
use swc_ecma_transforms_typescript::strip;
use swc_ecma_visit::{as_folder, FoldWith};
pub fn bundle_script(script: &str) -> String {
#[cfg(debug_assertions)]
let minify = false;
#[cfg(not(debug_assertions))]
let minify = true;
let output = GLOBALS.set(&Default::default(), || {
let cm = Arc::<SourceMap>::default();
let globals = Box::leak(Box::default());
let globals = &Box::default();
let mut bundler = Bundler::new(
globals,
cm.clone(),
Loader { cm: cm.clone() },
CachingResolver::new(
4096,
NodeModulesResolver::new(TargetEnv::Node, Default::default(), true),
NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true),
),
swc_bundler::Config {
require: false,
// disable_hygiene: !minify,
// disable_dce: !minify,
// disable_fixer: !minify,
// disable_inliner: !minify,
..Default::default()
},
Box::new(Hook),
@ -44,31 +58,32 @@ pub fn bundle_script(script: &str) -> String {
let modules = bundler.bundle(entries).expect("failed to bundle");
let mut buf = vec![];
{
let wr = JsWriter::new(cm.clone(), "\n", &mut buf, None);
let mut emitter = Emitter {
cfg: swc_ecma_codegen::Config {
minify,
..Default::default()
},
cm: cm.clone(),
comments: None,
wr: if minify {
Box::new(omit_trailing_semi(wr)) as Box<dyn WriteJs>
} else {
Box::new(wr) as Box<dyn WriteJs>
},
};
for module in modules {
emitter.emit_module(&module.module).unwrap();
}
for module in modules {
write(minify, cm.clone(), &module.module, &mut buf);
}
buf
});
String::from_utf8(output).expect("invalid utf8 bundle")
}
fn write<W: Write>(minify: bool, cm: Arc<SourceMap>, module: &Module, out: W) {
let wr = JsWriter::new(cm.clone(), "\n", out, None);
let mut emitter = Emitter {
cfg: swc_ecma_codegen::Config {
minify,
..Default::default()
},
cm: cm.clone(),
comments: None,
wr: if minify {
Box::new(omit_trailing_semi(wr)) as Box<dyn WriteJs>
} else {
Box::new(wr) as Box<dyn WriteJs>
},
};
emitter.emit_module(module).unwrap();
}
struct Hook;
impl swc_bundler::Hook for Hook {
@ -120,8 +135,11 @@ impl Load for Loader {
let module = parse_file_as_module(
&fm,
Syntax::Es(Default::default()),
EsVersion::Es2020,
Syntax::Typescript(TsConfig {
tsx: true,
..TsConfig::default()
}),
EsVersion::Es5,
None,
&mut vec![],
)
@ -132,6 +150,40 @@ impl Load for Loader {
panic!("failed to parse")
});
let top_level_mark = Mark::new();
let module = module
.fold_with(&mut strip(top_level_mark))
.fold_with(&mut as_folder(TransformVisitor::new(
jsx_dom_expressions::config::Config {
module_name: "solid-js/web/dist/web.js".to_string(),
builtins: vec![
"For".into(),
"Show".into(),
"Switch".into(),
"Match".into(),
"Suspense".into(),
"SuspenseList".into(),
"Portal".into(),
"Index".into(),
"Dynamic".into(),
"ErrorBoundary".into(),
],
..Default::default()
},
NoopComments,
)))
.fold_with(&mut hygiene())
.fold_with(&mut fixer(None));
// if let FileName::Real(path) = &f {
// let mut out = vec![];
// write(false, self.cm.clone(), &module, &mut out);
// let mut path = path.clone();
// path.set_extension("c.js");
// std::fs::write(path, out).unwrap();
// }
Ok(ModuleData {
fm,
module,