diff --git a/apprun-site-cli.js b/apprun-site-cli.js index a611d29..6775adc 100755 --- a/apprun-site-cli.js +++ b/apprun-site-cli.js @@ -73,7 +73,9 @@ program .action(async (source, options) => { ({ source, options } = await init_options(source, options)); options.info && console.log(options); + options.ssr = false; options.save = false; + options.dev = true; await build(options); server(options); }); diff --git a/server.js b/server.js index 777a114..7c0ef87 100644 --- a/server.js +++ b/server.js @@ -2,10 +2,12 @@ import { existsSync, statSync, writeFileSync, mkdirSync } from 'fs'; import { join, resolve } from 'path'; +import { readFileSync } from 'fs'; import express from 'express'; import bodyParser from 'body-parser'; import render from './src/render.js'; import { info, debug, error, warn } from './src/log.js'; +import vfs from './src/vfs.js'; export let config = {}; @@ -26,7 +28,8 @@ export default function (_config = {}) { app.use(bodyParser.urlencoded({ extended: true })); set_api(app, source); - set_push(app, source); + set_action(app, source); + set_vfs(app, root); set_ssr(app, root, port, ssr, save); app.use((err, req, res, next) => { @@ -38,6 +41,55 @@ export default function (_config = {}) { return app; } +export function set_vfs(app, root) { + app.use((req, res, next) => { + const reqPath = join(root, req.path); + if (vfs.has(reqPath)) { + const asset = vfs.get(reqPath); + res.set('Content-Type', asset.type); + res.send(asset.content); + return; + } + next(); + }); +} + +// export function send_live_reload(req, res, next) { +// const reqPath = req.path; +// if (reqPath.endsWith('.html') || reqPath === '/') { +// const filePath = join(root, reqPath === '/' ? 'index.html' : reqPath); +// if (existsSync(filePath)) { +// const data = readFileSync(filePath, 'utf8'); +// const injectedData = data.replace( +// /<\/body>/i, +// `` +// ); +// res.type('.html').send(injectedData); +// return; +// } +// } +// next(); +// } + export function set_ssr(app, root, port, ssr, save) { app.get('*', async (req, res, next) => { @@ -135,7 +187,7 @@ export function set_api(app, source) { }); } -export function set_push(app, source) { +export function set_action(app, source) { app.get('/_/*', async (req, res, next) => { try { @@ -175,7 +227,6 @@ export function set_push(app, source) { }); } - function find_js(req_path, root) { let path = req_path.replace('/_', ''); const segments = path.split('/').filter(segment => segment !== ''); diff --git a/src/build-css.js b/src/build-css.js index b933edd..d81ab25 100644 --- a/src/build-css.js +++ b/src/build-css.js @@ -3,6 +3,7 @@ import { existsSync, writeFileSync, readFileSync, copyFileSync } from 'fs'; import chalk from 'chalk'; const { cyan, yellow, blue, green, magenta, gray, red } = chalk; import { exec } from 'child_process'; +import vfs from './vfs.js'; export const build_tailwind = async (from, to, config) => { const { source, pages, output, relative, should_ignore } = config; @@ -44,7 +45,12 @@ export const build_css = async (from, to, config) => { console.warn(err.toString()); } + + vfs.set(to, result.css, 'text/css'); + // notifyChange('css', filePath); + writeFileSync(to, result.css); + console.log(cyan('Compiled CSS with PostCss'), relative(to)); } catch (err) { diff --git a/src/build.js b/src/build.js index 7b5d881..e3143ca 100644 --- a/src/build.js +++ b/src/build.js @@ -63,14 +63,9 @@ const render_routes = async ({ output, relative}) => { const run_build = async (config) => { const start_time = Date.now(); routes.length = 0; - // css_files.length = 0; await walk(config.pages, config); await build_main(config); - await run_bundle(config); - // for (const [from, to] of css_files) { - // await build_css(from, to, config); - // } - // css_files.length = 0; + // await run_bundle(config); const elapsed = Date.now() - start_time; console.log(cyan(`Build done in ${elapsed} ms.`)); } @@ -145,7 +140,7 @@ export default async (config) => { } }).on('ready', () => { ready = true; - console.log(cyan('Watching ...')); + console.log(yellow('Watching ...')); }); } } diff --git a/src/esbuild.js b/src/esbuild.js index 6163cf5..9ef909d 100644 --- a/src/esbuild.js +++ b/src/esbuild.js @@ -3,8 +3,11 @@ import esbuild from 'esbuild'; import chalk from 'chalk'; const { cyan, yellow, blue, green, magenta, gray, red } = chalk; import conditionalCompilePlugin from './esbuild-plugin.js'; +import vfs from './vfs.js'; -export default async function (file, target, options = {}) { +export default build_in_memory; + +export async function build(file, target, options = {}) { try { const result = await esbuild.build({ entryPoints: [file], @@ -22,6 +25,34 @@ export default async function (file, target, options = {}) { } } +export async function build_in_memory (file, target, options = {}) { + try { + const result = await esbuild.build({ + entryPoints: [file], + outfile: target, + format: 'esm', + bundle: true, + sourcemap: true, + minify: false, + ...options, + write: false, + }); + result.errors.length && console.log(red(result.errors)); + result.warnings.length && console.log(yellow(result.warnings)); + + if (result.outputFiles) { + result.outputFiles.forEach(f => { + const filePath = f.path; + const moduleKey = filePath.replace(/\\/g, '/'); + vfs.set(moduleKey, f.text, 'application/javascript;charset=UTF-8'); + }) + // notifyChange('js', filePath); + } + } catch (e) { + console.log(red(e.message)); + } +} + export async function bundle(output, entryPoints) { try { const result = await esbuild.build({ diff --git a/src/vfs.js b/src/vfs.js new file mode 100644 index 0000000..8b88f02 --- /dev/null +++ b/src/vfs.js @@ -0,0 +1,23 @@ +import fs from 'fs'; +import path from 'path'; + +const assets = new Map(); + +export const clean = () => assets.clear(); + +const set = (key, content, type) => assets.set(key, { content, type }); + +export const get = (key) => assets.get(key); + +export const has = (key) => assets.has(key); + +export const dump = (outputDir) => { + for (const [key, asset] of assets.entries()) { + const { content } = asset; + const outputPath = path.join(outputDir, key); + fs.mkdirSync(path.dirname(outputPath), { recursive: true }); + fs.writeFileSync(outputPath, content); + } +} + +export default { has, set, get, clean, dump }; \ No newline at end of file