npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@melt-js/tpl-vue3-admin-ele-pure

v2026.11.8

Published

由 pure-admin-thin 提取的 Vue 3 + Element Plus 后台模板,公共组件改为从 comps-pure 远程加载

Readme

tpl-vue3-admin-ele-pure

由 pure-admin-thin 提取的 Vue 3 + Element Plus 后台模板(Vite 8 + Tailwind 4 + pinia + vue-router)。

与其他 tpl 包不同,本包不做成远程组件对外暴露:它就是一个普通的后台应用模板,只是把原仓库 src/components 里的公共组件、src/layout 里的布局抽到了远程包 comps-pure,运行时用 preFetchLib('comps-pure') 加载。构建产物会打包发布到 npm,用 unpkg 托管线上 demo(见发布到 unpkg)。

本包只是把上游 pure-admin-thin 的源码整理进 monorepo,请遵守上游的使用约定。

快速开始

# 终端 1:公共组件远程包(端口 20070)
pnpm comps-pure:dev

# 终端 2:后台模板(端口 50130)
pnpm tpl3-pure:dev

打开 http://localhost:50130/,用户名 admin 或 common、密码任意(mock 登录见 mock/login.js:admin 拥有 *:*:* 权限,common 只有 permission:btn:add / permission:btn:edit)。

pnpm build        # 产物在 dist/,远程组件地址切到 unpkg 上的 hel-meta.json
pnpm preview      # 预演 dist(50140)

发布到 unpkg

# 发布前先按仓库 calver 规则把 package.json 的 version 改成今天(如 2026.11.7)
pnpm --filter @melt-js/tpl-vue3-admin-ele-pure run publish:stage

线上入口:https://unpkg.com/@melt-js/tpl-vue3-admin-ele-pure/dist/index.html(unpkg 字段已指向它,直接访问包名也会跳转)。

  • publish:stage = pnpm run build && npx -y npm@11 stage publish,只把版本暂存到 npm;执行 npm stage list --registry=https://registry.npmjs.org 拿到 stage id 后,还要 npm stage approve <stage-id> 才真正上线;
  • files 白名单只发布 dist/、README.md、LICENSE,不含源码与 mock/ 源码;mock 会随产物打进 dist,所以打开线上页面即可用 admin / 任意密码登录;
  • publishConfig.registry 指向 https://registry.npmjs.org,仓库根 .npmrc 的 npmmirror 只读镜像不参与发布。

公共组件为什么在远端

原仓库的 src/components 是一个「宿主强耦合」的组件目录:ReAuth 依赖 @/router/utils 的 hasAuth、RePerms 依赖 @/utils/auth 的 hasPerms、PureTableBar 依赖 @/store/modules/epTheme 的主题色。抽到 comps-pure 后:

  • 这些宿主能力改成运行时注入:lib.setupPureRuntime({ hasAuth, hasPerms, getEpThemeColor })(src/remote/setup.js);
  • 组件包不 import 宿主的任何模块,因此可以独立调试(未注入时权限默认放行);
  • 模板不再把 ReIcon / ReDialog / ReText / ReSegmented / PureTableBar / Auth / Perms 打进自己的产物。

模板里的用法保持不变:

| 位置 | 用法 | | --- | --- | | src/main.js | 固定启动骨架:bindVueRuntime → loadRemoteComps → 平台配置 → setupStore → setupRemoteComps → app.use(router) → storage / 插件 → router.isReady → mount(远程包必须在路由首次导航前就绪) | | src/remote/setup.js | 预加载远程包、注入 hasAuth / hasPerms / getEpThemeColor / 布局能力 / 工具用户 store、注册远程指令、全局注册 10 个组件 | | src/remote/index.js | 函数式 API 的本地代理:useRenderIcon / addDialog / closeDialog / closeAllDialog / addOfflineIcons(远程包就绪前会缓存离线图标注册);路由级布局 / 异常页用 defineRemoteRoute 等同一个 preFetchLib Promise | | src/plugins/offlineIcons.js | 把路由 / mock 用到的图标(ep:home-filled、ep:lollipop、ri:search-line 等)交给远程包的 addOfflineIcons 预注册,断网时图标也能显示 | | src/App.vue | <ReDialog /> 直接用全局组件;closeAllDialog 走本地代理 | | src/layout/** | 只剩 types.js(routerArrays 常量);路由组件直接在 src/router/modules/*.js 里 defineRemoteRoute("ReLayout") / defineRemoteRoute("LayFrame") / defineRemoteRoute("LayRedirect"),布局 hooks 直接用 lib.useNav() / lib.useLayout() 等 | | src/utils/** | 只剩 auth.js 的常量(userKey / TokenKey / multipleTabsKey);message / http / progress / mitt / responsive 等转发文件已删除,调用处直接使用 lib.xxx | | src/directives/** | 已删除;v-auth / v-perms 等由 setupRemoteComps 从 lib.directives 统一注册 | | src/plugins/elementPlus.js | 已删除;lib.setupElementPlus(app) 按 window.ElementPlus 命名空间自动注册,2.14 新增组件无需改模板 | | src/config/index.js | 只保留 getPlatformConfig(依赖 VITE_PUBLIC_PATH + axios);getConfig / setConfig 转发到远程 config | | src/views/error/*.vue | 已删除;/error/403|404|500 等路由直接 defineRemoteRoute("Error403/404/500"),页面与插画在远程包 | | src/style/** | transition.scss / element-plus.scss / dark.scss 已移到远程包;reset.scss / sidebar.scss / theme.scss / tailwind.css 属于本模板主题体系,保留 |

远程组件只有一个入口:src/remote/

所有「知道组件来自远程」的代码都收在这里,以后同步公共组件只需要动这个目录:

src/remote/
  config.js   远端地址推导(dev 用 http://localhost:20070,build 用 unpkg 上的 hel-meta.json)+ preFetchLib
  setup.js    启动期注入:bindVueRuntime / element-plus / setupPureRuntime / setupLayoutRuntime / setupUtilsRuntime / 全局组件 / 指令
  index.js    业务侧访问器(getRemoteComps / defineRemoteRoute / addOfflineIcons ...)

业务代码不需要感知远程。comps-pure 的包入口就是 hel 的 exposeLib 代理, preFetchLib 完成后可以像普通 npm 包一样使用:

import lib from "@melt-js/comps-pure";

lib.useRenderIcon("ri:search-line");   // 函数
lib.addDialog({ title: "..." });       // 弹窗
lib.getStaticUrl("static/bg.png");     // 远程包托管的静态资源

组件本身在 setupRemoteComps 里已全局注册,模板里直接写 <ReText /> / <Auth /> / <ReDialog />, 既不需要 import、也不需要 defineRemoteRoute(后者只用于路由级懒加载的布局与异常页, 作用是等同一个 preFetchLib Promise,避免首屏直接刷新布局路由时抢跑)。

布局也在远端

src/layout 的实现已经搬进 comps-pure/src/layout,本模板不再保留适配层:

  • 路由组件:在 src/router/modules/*.js 里直接 defineRemoteRoute("ReLayout") / defineRemoteRoute("LayFrame") / defineRemoteRoute("LayRedirect");
  • 布局 hooks:在使用的页面直接 lib.useNav() / lib.useLayout() / lib.useTags() / lib.useDataThemeChange(),不再经过 src/layout/hooks/*;
  • src/layout/types.js 保留 routerArrays 常量(依赖 VITE_HIDE_HOME),由 setupLayoutRuntime 回传。

布局需要的 pinia store / router / i18n / 主题 / 头像等能力,在 src/remote/setup.js 的 setupRemoteLayout(lib) 里通过 lib.setupLayoutRuntime({...}) 注入。精简版的能力开关是 features: { i18n: false, watermark: true },与完整版共用同一份布局实现。原来 src/layout/index.vue 里全局引入的 animate.css、@/plugins/offlineIcons 已移到 src/main.js。

公共工具 / 指令也在远端

除布局外,两个模板重复的工具与指令也合并进了远程包:

  • src/utils/** 只保留 auth.js 的常量;message / http / progress / print / localforage / preventDefault / responsive 的转发文件已删除,调用处直接使用 lib.message / lib.http / lib.NProgress / lib.injectResponsiveStorage 等;src/utils/tree.js 直接删除,改用 @pureadmin/utils 的同名树工具;
  • src/directives/** 删除,auth / perms / copy / longpress / optimize / ripple 从 lib.directives 注册;
  • src/plugins/elementPlus.js 删除,改由远程 lib.setupElementPlus(app) 自动注册(不再维护 2.14 的组件长列表);
  • src/plugins/echarts.js 未被任何页面引用,已删除;
  • src/views/error/** 只保留适配层,异常页与插画在远程包;src/assets/status 删除;
  • src/config/index.js 只保留 getPlatformConfig,配置读写走远程 config;完整版 i18n 初始语言在配置加载后调用 initI18nLocale();
  • src/style/ 中两个模板一致的 transition.scss / element-plus.scss / dark.scss 移到远程包,reset.scss / sidebar.scss / theme.scss / tailwind.css 留在模板;
  • 登录态 / HTTP 需要读写用户 store,由 lib.setupUtilsRuntime({ useUserStoreHook }) 注入。

固定启动骨架

src/main.js 两个模板保持同一顺序,业务开发只需要改 views/ / api/ / 路由与 store:

bindVueRuntime({ Vue });                 // 1 共享 vue 运行时
setRemoteComps(await loadRemoteComps()); // 2 预加载远程组件
const config = await getPlatformConfig(app); // 3 平台配置
setupStore(app);                         // 4 pinia
await setupRemoteComps(app);             // 5 注入纯/布局/工具运行时 + 注册指令/组件
app.use(router);                         // 6 首次导航(守卫已可用远程 auth/http)
injectResponsiveStorage(app, config);    // 7 storage / UI 插件
app.use(MotionPlugin).use(Table).use(VueTippy);
await router.isReady();
app.mount("#app");

关键点:远程包必须在 app.use(router) 之前就绪,因为首次导航的守卫会调用远程的 removeToken / NProgress / http。

远端地址按环境选择(src/configs/remote.js):开发 http://localhost:20070,构建 https://unpkg.com/@melt-js/comps-pure/hel_dist/hel-meta.json,可用 VITE_REMOTE_HOST 覆盖(例如指向自己部署的 hel-meta.json)。远程包加载失败时,main.js 会渲染一个带远端地址与错误原因的兜底页,不会白屏。

与上游仓库的差异

  • 删除 src/components/**(已抽到 comps-pure)与 src/assets/table-bar/**(随 PureTableBar 一起搬走);
  • 删除 src/layout/components/** 与布局 hooks 的具体实现(已抽到 comps-pure/src/layout),本地只保留 index.vue / frame.vue / redirect.vue 适配层、hooks/* 转发和 types.js;
  • 布局的宿主依赖改成运行时注入(lib.setupLayoutRuntime):store / router / 平台配置 / 头像 / emitter 等从 src/remote/setup.js 传入;布局图标已内联到远程包,不再依赖 vite-svg-loader / unplugin-icons;
  • 原 src/layout/index.vue 里的 animate.css、@/plugins/offlineIcons 移到 src/main.js,避免异步布局加载时主题动画和图标注册滞后;
  • src/plugins/offlineIcons.js 预注册路由 / mock 用到的 4 个图标,断网时菜单图标也能显示;
  • src/utils/** 与 src/directives/** 的公共实现已抽到 comps-pure:utils 只保留 auth.js 常量,其余转发文件删除、调用处直接用 lib.xxx;directives 目录删除、改由 lib.directives 注册;src/utils/tree.js 删除(改用 @pureadmin/utils);
  • axios 实例、拦截器、mock { success, data } 兼容、NProgress 都在远程包,API 模块直接 lib.http.request/get/post,不再保留本地 http 转发文件;
  • src/plugins/elementPlus.js / src/plugins/echarts.js 删除:element-plus 由远程包自动注册,echarts 插件模板中无引用;
  • src/views/error/*.vue 改为远程组件适配层,src/assets/status 删除;src/style/transition.scss、element-plus.scss、dark.scss 移到远程包;
  • 随代码迁到远程包的依赖(pinyin-pro / path-browserify / echarts / localforage / mitt / nprogress / qs / responsive-storage,以及本模板未使用的 dayjs)已从 package.json 移除;
  • 删除 husky / commitlint / lint-staged / Dockerfile / .dockerignore / 上游 .npmrc(monorepo 用根目录统一管理),保留 eslint / prettier / stylelint 配置与脚本;
  • 端口写死为 50130(dev)/ 50140(preview),并在根目录 ports.json 登记;
  • build/info.js 打包信息插件改用 writeBundle:Vite 8(rolldown)在 closeBundle 时产物可能还没落盘,统计 dist 会抛 ENOENT 把构建带崩;
  • 删除 .browserslistrc,只保留 package.json 的 browserslist(两者同时存在会让 cssnano 报 "contains both .browserslistrc and package.json with browsers");
  • vite.config.js 增加 watch.ignored: [/\.tmpdir([\\/]|$)/]:Windows 上 chokidar 命中原子写入的临时目录会抛 EBUSY 把 dev server 带崩;
  • .env.production 的 VITE_PUBLIC_PATH 为 ./:配合 hash 路由,dist/index.html 从任意层级的路径(如 unpkg)打开都能加载同目录资源;部署到服务器根目录时改回 / 也可以。

目录结构(只列关键项)

build/                打包插件(tailwind / jsx / icons / fake-server / 压缩 / 构建信息)
mock/                 登录与动态路由 mock
public/               favicon、logo、platform-config.json
src/
  api/                接口
  layout/             types.js(routerArrays 常量);布局组件由 defineRemoteRoute 直接加载
  plugins/            element-plus 按需注册、远程组件接入、离线图标
  remote/             config.js / setup.js / index.js(远程包唯一入口)
  router/             静态 / 动态路由(ReLayout / LayFrame / LayRedirect 用 defineRemoteRoute)
  store/              pinia
  style/              重置 / element-plus / tailwind / 暗色
  utils/              仅 auth.js 常量;其余工具直接调用 lib.*
  views/              login / welcome / permission / error

端口

| 用途 | 端口 | | --- | --- | | dev(pnpm dev) | 50130 | | preview(pnpm preview) | 50140 | | 依赖的远程组件 comps-pure | 20070 |