Phoenix 前端资产与样式开发规范:Tailwind CSS、JS/CSS 构建与 UI/UX 设计指南

Phoenix 前端资产与样式开发规范:Tailwind CSS、JS/CSS 构建与 UI/UX 设计指南 Phoenix 前端资产与样式开发规范Tailwind CSS、JS/CSS 构建与 UI/UX 设计指南【免费下载链接】phoenixPeace of mind from prototype to production项目地址: https://gitcode.com/gh_mirrors/ph/phoenix导读本指南基于 Phoenix 仓库中随应用脚手架一起生成的usage-rules/assets.md规范文档系统讲解在 Phoenix 项目中编写 JavaScript 与 CSS 的硬性规则、Tailwind CSS 与 daisyUI 的正确使用方式、vendor 依赖的唯一合法引入途径以及 UI/UX 设计的落地准则。读完本文你将掌握 Phoenix 生成应用assets/目录下app.js与app.css的构建原理esbuild Tailwind v4、如何在不破坏框架约定前提下引入第三方库并理解仓库模板与构建配置app.css.eex、app.js.eex、config.exs.eex之间的对应关系。一、资产使用总则开箱即用的两个 Bundle规范第一条即明确开箱即用Out of the box只支持app.js与app.css两个构建产物bundle。所有页面资源都必须汇聚到这两个入口文件中由构建工具统一打包输出到priv/static/assets/。这意味着两条硬性约束不能在布局模板中直接引用外部 vendor 脚本的src或样式表的href例如 CDN 上的 jQuery、某个图标库或字体 CSS必须把 vendor 依赖import进app.js/app.css后使用让依赖参与本地打包。从脚手架模板可以清楚看到这两个入口的原始形态JS 入口 app.js.eex 中注释明确给出了两种引入 vendor 依赖的推荐方式将依赖放入assets/vendor目录使用相对路径导入import ../vendor/some-package.js或在assets目录执行npm install some-package --prefix assets再以包名导入import some-package。CSS 入口 app.css.eex 采用 Tailwind CSS v4 的import tailwindcss source(none);作为根指令并通过多个source指令声明扫描范围见下一节。模板还特别提示若某个依赖会尝试引入 CSSesbuild 会为其生成独立的app.css文件此时需要在root.html.heex中追加第二个link标签来加载它——这是“只支持两个 bundle”原则下唯一的例外路径且仍属于本地打包产物而非外部链接。二、样式开发规范Tailwind 优先、禁止apply、不用 daisyUI 组件2.1 使用 Tailwind CSS 类与自定义 CSS 规则规范要求使用Tailwind CSS 类 自定义 CSS 规则打造精致、响应式、视觉出众的界面。仓库生成的 app.css.eex 展示了 Tailwind v4 的标准接线方式import tailwindcss source(none); import phoenix-colocated/% web_app_name %/colocated.css; source ../css; source ../js; source ../../lib/% lib_web_name || app_name %; /* Required for Tailwind to automatically pick up changes in colocated CSS files in dev */ source % if in_umbrella do %../../% end %../../_build/dev/phoenix-colocated/% web_app_name %/*/;source(none)表示关闭 Tailwind 的自动内容探测由显式source指令接管扫描范围source ../css与source ../js扫描assets目录下的样式与脚本source ../../lib/...让 Tailwind 能识别.heex模板与 colocated CSS 中的类名最后一行确保开发环境下 colocated CSS 的变更能被 Tailwind 自动拾取。2.2 绝对禁止在原始 CSS 中使用apply规范原文为Never useapplywhen writing raw css即手写原始 CSS 时严禁使用 Tailwind 的apply指令。这条约束避免了apply与 Tailwind v4 新 CSS 引擎之间潜在的编译歧义也强制开发者以“纯 CSS 自定义属性 Tailwind 工具类”的方式组织样式保证生成的 CSS 可预测、可排查。2.3 用自研 Tailwind 组件替代 daisyUI规范要求编写自己的 Tailwind 组件而不是使用 daisyUI以获得独特、世界级world-class的设计风格。需要说明的是仓库模板虽在 app.css.eex 中通过plugin daisyui/packages/bundle/daisyui与plugin daisyui/packages/bundle/daisyui-theme引入了 daisyUI 的主题系统内置一套受 Phoenix 配色启发的浅色主题与受 Elixir 配色启发的深色主题均以 oklch 色值定义但规范明确要求界面组件按钮、卡片、表单等应由开发者基于 Tailwind 自行实现daisyUI 仅作为主题变量来源不直接复用其现成组件类。模板中可直接观察到这套主题接线plugin daisyui/packages/bundle/daisyui { themes: false; } plugin daisyui/packages/bundle/daisyui-theme { name: dark; default: false; prefersdark: true; color-scheme: dark; --color-base-100: oklch(30.33% 0.016 252.42); /* ... 其余语义色、圆角、边框、深度等设计令牌 ... */ } plugin daisyui/packages/bundle/daisyui-theme { name: light; default: true; prefersdark: false; /* ... */ }浅色主题为默认default: true深色主题通过prefersdark: true跟随系统偏好。开发时可通过data-themedark属性手动切换——这一点在文件末尾有专门声明/* Use the data attribute for dark mode */ custom-variant dark (:where([data-themedark], [data-themedark] *));三、构建管线esbuild 与 Tailwind 的配置对应关系规范中“只支持两个 bundle”的落点是脚手架mix.exs与config.exs中的构建配置。以单应用非 umbrella模板为例在 mix.exs.eex 中声明构建工具依赖仅在 dev 环境作为 runtime 依赖避免生产环境重复执行构建{:esbuild, ~ 0.10, runtime: Mix.env() :dev}, {:tailwind, ~ 0.5, runtime: Mix.env() :dev}, {:heroicons, github: tailwindlabs/heroicons, tag: v2.2.0, sparse: optimized, app: false, compile: false, depth: 1}, {:daisyui, github: saadeghi/daisyui, tag: v5.5.20, sparse: packages/bundle, app: false, compile: false, depth: 1},对应在 config.exs.eex 中给出 esbuild 与 Tailwind 的二进制版本与参数# Configure esbuild (the version is required) config :esbuild, version: 0.25.4, % app_name %: [ args: ~w( js/app.js --bundle --formatesm --targetes2022 --outdir../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:. ), cd: Path.expand(.../assets, __DIR__), env: %{NODE_PATH [Path.expand(../deps, __DIR__), Mix.Project.build_path()]} ] # Configure tailwind (the version is required) config :tailwind, version: 4.3.0, % app_name %: [ args: ~w( --inputassets/css/app.css --outputpriv/static/assets/css/app.css ), cd: Path.expand(..., __DIR__), ... ]要点解读esbuild 以js/app.js为入口输出 ESM 格式--formatesm目标环境es2022产物落入priv/static/assets/js--external:/fonts/*与--external:/images/*将字体、图片资源排除在打包之外交由运行时路径解析NODE_PATH指向deps使得 JS 里import phoenix_html、import phoenix_live_view这类裸包名导入能解析到 mix 依赖目录Tailwind v4 以assets/css/app.css为输入、产出priv/static/assets/css/app.css正是第一节中那套import指令所在的文件。配合mix.exs中定义的 aliases日常资产操作全部封装为 mix 命令assets.setup: [esbuild.install --if-missing, tailwind.install --if-missing], assets.build: [compile, esbuild % app_name %, tailwind % app_name %], assets.deploy: [esbuild % app_name % --minify, tailwind % app_name % --minify, phx.digest],开发中运行mix assets.setup安装构建二进制mix assets.build增量编译生产部署运行mix assets.deploy压缩 指纹化 静态资源摘要。这些命令与“只支持app.js/app.css”的约束共同保证了priv/static/assets/下产物的确定性。四、vendor 依赖的唯一合法引入途径规范将外部资源访问收敛为一条路径把依赖打进本地 bundle。具体分为两步全部在assets目录内完成将第三方库文件放入assets/vendor/如仓库自带的 topbar.js.eex即 topbar 3.0.0 的 vendor 副本然后在app.js中相对导入或通过npm install pkg --prefix assets安装后以包名导入。对应地root.html.heex布局中不允许出现指向外部 CDN 的script src...与link href...自定义脚本也必须收敛进app.js严禁在模板内联scriptcustom js/script见第五节。这条规则的底层原因可以从 tsconfig.json.eex 窥见脚手架项目默认没有node_modulesesbuild 通过paths别名把裸导入映射到../deps/*即 mix 依赖目录若项目引入了package.json才需要把phoenix、phoenix_html、phoenix_live_view等声明进 dependencies 指向../deps/...。换言之不建立额外 node_modules 环境、依赖统一由 Hex/mix 管理是这套资产体系的设计前提。一个典型的app.js接线来自 app.js.eexLiveView 场景展示了 vendor 依赖如何汇入单入口import phoenix_html import {Socket} from % phoenix_js_path % import {LiveSocket} from phoenix_live_view import {hooks as colocatedHooks} from phoenix-colocated/% web_app_name % import topbar from ../vendor/topbar const csrfToken document.querySelector(meta[namecsrf-token]).getAttribute(content) const liveSocket new LiveSocket(/live, Socket, { longPollFallbackMs: 2500, params: {_csrf_token: csrfToken}, hooks: {...colocatedHooks}, }) topbar.config({barColors: {0: #29d}, shadowColor: rgba(0, 0, 0, .3)}) window.addEventListener(phx:page-loading-start, _info topbar.show(300)) window.addEventListener(phx:page-loading-stop, _info topbar.hide()) liveSocket.connect() window.liveSocket liveSocket其中phoenix_html、phoenix_live_view均为经NODE_PATH解析的 mix 依赖topbar则是vendor目录中的本地副本——两类 vendor 引入方式在同一入口文件里并存示范。开发环境下phx:live_reload:attached事件还会启用浏览器控制台的服务端日志流式输出并支持按住c键点击元素跳转到调用处、按住d键跳转到组件定义处配合PLUG_EDITOR。五、模板内禁止内联脚本规范最后一条硬约束绝不Never在模板中编写内联scriptcustom js/script标签。所有行为逻辑必须进入app.js及其导入的模块。理由包括内联脚本无法参与 esbuild 打包无法享受依赖解析、压缩、指纹化等收益内联脚本绕过 CSP 与内容安全策略的审计面且无法被 LiveView 的更新机制管理与“单一 bundle 入口”约定冲突导致行为代码分散、难以测试与复用。非 LiveView 页面若有少量 DOM 行为如 flash 消息关闭也应像 app.js.eex 非 LiveView 分支那样以模块化方式集中编写document.querySelectorAll([rolealert][data-flash]).forEach((el) { el.addEventListener(click, () { el.setAttribute(hidden, ) }) })六、UI/UX 与设计规范规范第二部分给出了与资产工程配套的设计产出要求核心是“世界级 UI”world-class UI designs要点如下可用性、美学与现代设计原则并重布局、配色、层级以用户体验为先实现微妙的微交互如按钮 hover 效果、平滑过渡smooth transitions用最小成本提升操作反馈保证排版、间距与布局平衡追求精致、高端premium的视觉质感关注令人愉悦的细节hover 状态、加载状态loading states、平滑的页面转场。这些设计准则在工程层面与资产规范互相支撑例如加载状态可直接复用 topbar.js.eex 实现的页面顶部进度条配合phx:page-loading-start/stop事件而 hover 与过渡效果则依赖 Tailwind 工具类hover:、transition-*在 app.css.eex 中声明的 LiveView 加载变体phx-click-loading、phx-submit-loading、phx-change-loading的custom-variant得以呈现。七、与 UI 组件体系的协同约定虽然assets.md主要面向资产与样式但其规则与仓库其他 usage-rules如 phoenix.md中 UI 组件约定是配套的图标一律使用core_components.ex引入的.icon组件内部由 heroicons.js.eex 生成的hero-*Tailwind 组件类驱动类名如hero-x-mark会自动从deps/heroicons/optimized目录读取对应 SVG 并以内联 data URI mask 方式渲染表单输入优先使用.input组件——这些组件本身正是“基于 Tailwind 自定义组件”这一规范的最佳实践产物也解释了为何不推荐用 daisyUI 组件类统一由core_components提供的组件族才能保证全站风格一致且可定制。结语Phoenix 的前端资产规范可以概括为三句话一切资源汇入app.js与app.css两个 bundle样式以 Tailwind 类为主、原始 CSS 不用apply、组件自研不套 daisyUI模板内零内联脚本、零外部 vendor 链接。配合脚手架中 esbuild/Tailwind 的版本化配置与mix assets.*系列任务这套体系让团队在获得现代构建能力的同时保持产物的可预测、可审计与可部署性。开发者在遵循以上规则时可随时对照仓库模板app.css.eex、app.js.eex、config.exs.eex、mix.exs.eex验证自己的接线方式是否与脚手架约定一致。【免费下载链接】phoenixPeace of mind from prototype to production项目地址: https://gitcode.com/gh_mirrors/ph/phoenix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考