无打包 →
src/目录结构会原样上传到 OBS(不存在 tree-shaking / 文件重命名 / hash), 所以目录即 URL 路径,文件即模块。摆放必须克制、可预测。
src/
index.html # 入口:<base> + <script type="importmap"> + <script type="module" src="./app.js">
app.js # 应用装配:全局 DI provide + 路由挂载 + 根组件渲染 + 多标签
components/ # 通用组件(可跨页复用)
side-menu.js
user-card.js
tabs-container.js
routes/ # 页面级组件(一页一文件)
page-user-list.js
page-user-detail.js
page-404.js
services/ # 业务服务(状态 + 接口 + 计算)
auth-service.js
table-service.js
router-service.js
utils/ # 无状态工具
http.js
storage.js
format.js
examples/hello-lit/ 是本规范的完整可运行样例。
| 类型 | 文件 | 类 / 导出 | 自定义元素标签 |
|---|---|---|---|
| 通用组件 | kebab-case.js |
PascalCase(如 UserCard) |
kebab-case(<user-card>,必须含连字符) |
| 页面组件 | page-xxx.js |
PageXxx |
<page-xxx> |
| 服务 | xxx-service.js |
XxxService |
单例:export const xxxService = new XxxService() |
| 工具 | xxx.js |
具名导出纯函数 | — |
无构建下浏览器按 URL 解析相对 import:
// 在 /projects/admin/routes/page-user-list.js 中
import { authService } from '../services/auth-service.js'; // → /projects/admin/services/auth-service.js
因此:
.js 后缀(浏览器原生 ESM,不做扩展名补全)。❌ import x from './foo'子目录部署(如 /projects/admin/)时,必须在 index.html 的 <head> 写 <base href>:
<base href="/<project>/"><!-- 例:/admin/ 或 /dev/fmode-app/ -->
否则浏览器会把 ./app.js 解析到域名根,相对 JS 全部 404。
<base> 影响:所有相对 URL(href/src/fetch 相对路径/import 裸相对路径)。base 或应用前缀拼装,见 routing.md。<base href> + importmap 里的业务前缀(若有)。node_modules 里放 lit 供运行时 import。lit 源码拷进 src/。index.html 的 importmap 指向 FMODE Repose 解析,见 deployment.md。本地 npm install lit @lit-labs/* 仅用于 IDE/TS 类型提示,不参与产物。
// package.json —— 仅开发期类型提示,不打包
{
"private": true,
"devDependencies": { "lit": "^3.2.0", "@lit-labs/signals": "^0.1.0" },
"scripts": { "deploy": "bash scripts/deploy.sh" }
}
| 这个东西是… | 放哪 |
|---|---|
| 全站复用的 UI(菜单、卡片、弹层) | components/ |
| 一个路由对应的一整页 | routes/page-*.js |
| 有状态、要跨页共享的业务逻辑 | services/*-service.js |
| 无状态、纯计算的函数 | utils/ |
| 全局装配(DI、路由、根标签) | app.js |
| 第三方运行时依赖 | 不放项目里,走 Repose + importmap |