tangxiangmin / vite-plugin-auto-skeleton

A scheme for automatically generating a skeleton screen
19 stars 6 forks source link

无法在vite项目中使用 #2

Open M69W opened 3 months ago

M69W commented 3 months ago

从 npm 看到 vite-plugin-auto-skeleton npm i vite-plugin-auto-skeleton vite 项目使用 pnpm pnpm i vite-plugin-auto-skeleton

vite.config.js

import {
  SkeletonPlaceholderPlugin,
  SkeletonApiPlugin
} from "vite-plugin-auto-skeleton";

...
plugins: [
      SkeletonPlaceholderPlugin(),
      vue(),
      SkeletonApiPlugin(),
...

index.html

<div id="app">__SKELETON_CONTENT__</div>

package.json

{
  "engines": {
    "node": ">= 16"
  },
  "dependencies": {
    "vite-plugin-auto-skeleton": "^1.0.0",
    "vue": "^3.4.27",
  },
  "devDependencies": {
    "vite": "^5.2.11",
  }
}

node -v

v16.18.0

报错

F:\viteMobile>pnpm dev

> viteMobile@0.0.1 dev F:\viteMobile
> set VITE_CJS_IGNORE_WARNING=true & vite --mode dev

X [ERROR] Failed to resolve entry for package "vite-plugin-auto-skeleton". The package may have incorrect main/module/exports specified in its package.json. [plugin externaliz
e-deps]

    node_modules/.pnpm/esbuild@0.20.2/node_modules/esbuild/lib/main.js:1374:27:
      1374 │         let result = await callback({
           ╵                            ^

    at packageEntryFailure (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/
dist/node/chunks/dep-cNe07EU9.js:48264:17)
    at resolvePackageEntry (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/
dist/node/chunks/dep-cNe07EU9.js:48261:5)
    at tryNodeResolve (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/dist/
node/chunks/dep-cNe07EU9.js:48031:20)
    at resolveByViteResolver (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vit
e/dist/node/chunks/dep-cNe07EU9.js:68607:32)
    at file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/dist/node/chunks/dep-
cNe07EU9.js:68639:40
    at requestCallbacks.on-resolve (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1374:28)
    at handleRequest (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:732:17)
    at handleIncomingPacket (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:757:7)
    at Socket.readFromStdout (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:680:7)
    at Socket.emit (node:events:513:28)

  This error came from the "onResolve" callback registered here:

    node_modules/.pnpm/esbuild@0.20.2/node_modules/esbuild/lib/main.js:1293:20:
      1293 │       let promise = setup({
           ╵                     ^

    at setup (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/dist/node/chun
ks/dep-cNe07EU9.js:68624:27)
    at handlePlugins (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1293:21)
    at buildOrContextImpl (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:979:5)
    at Object.buildOrContext (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:788:5)
    at F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:2215:15
    at new Promise (<anonymous>)
    at Object.build (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:2214:25)
    at build (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:2047:51)
    at bundleConfigFile (file:///F:/viteMobile/node_modules/.pnpm/vite@5.2.11_@types+node@20.11.30_less@4.2.0_sass@1.53.0_terser@5.29.2/node_modules/vite/dis
t/node/chunks/dep-cNe07EU9.js:68583:26)

  The plugin "externalize-deps" was triggered by this import

    vite.config.js:19:7:
      19 │ } from "vite-plugin-auto-skeleton";
         ╵        ~~~~~~~~~~~~~~~~~~~~~~~~~~~

failed to load config from F:\viteMobile\vite.config.js
error when starting dev server:
Error: Build failed with 1 error:
node_modules/.pnpm/esbuild@0.20.2/node_modules/esbuild/lib/main.js:1374:27: ERROR: [plugin: externalize-deps] Failed to resolve entry for package "vite-plugin-auto-skeleton".
The package may have incorrect main/module/exports specified in its package.json.
    at failureErrorWithLog (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1651:15)
    at F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1059:25
    at runOnEndCallbacks (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1486:45)
    at buildResponseToResult (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1057:7)
    at F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:1086:16
    at responseCallbacks.<computed> (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:704:9)
    at handleIncomingPacket (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:764:9)
    at Socket.readFromStdout (F:\viteMobile\node_modules\.pnpm\esbuild@0.20.2\node_modules\esbuild\lib\main.js:680:7)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12)
 ELIFECYCLE  Command failed with exit code 1.

F:\viteMobile>
tangxiangmin commented 3 months ago

这个应该是之前的包构建的问题,没想到这个包还有人关注,晚上花了一点时间重新进行了构建,现在可以安装新的版本npm i vite-plugin-auto-skeleton@1.1.0。同时需要安装peerDependencies包括body-parserfs-extra

另外更新了文档和示例项目的代码,也可以直接克隆项目,切换到example-vue目录下进行预览,这一步需要先运行npm run build构建之后才能使用

M69W commented 3 months ago

能生成骨架图了

但刷新显示有点异常? 自动生成的 src/skeleton/content.json 有问题?

2024523152050

现象描述

1、如果只在 index.html 添加 骨架会,src/skeleton/content.json 生成如下

{"__SKELETON_undefined_CONTENT__":{"content":"<div class=\"__skeleton_undefined_content__\"></div>","pathname":"/"}}

2、只要在【index.html、src/views/demo/index.vue】两处都添加 骨架图,src/skeleton/content.json 貌似正常,但刷新页面显示却不太正常

{"__SKELETON_undefined_CONTENT__":{"content":"<div class=\"__skeleton_undefined_content__\"></div>","pathname":"/"},"__SKELETON_DEMO_CONTENT__":{"content":"<div class=\"__skeleton_demo_content__\"><div class=\"demo-content px-[12px] sk\"><img class=\"block w-[120px] mx-auto mb-[20px] pt-[30px]\" alt=\"Vue logo\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" style=\"background: rgb(238, 238, 238);\"><div class=\"pl-[12px] border-l-[3px] border-[color:#41b883] sk-border\"><a class=\"flex items-center\" href=\"https://github.com/yulimchen/vue3-h5-template\" target=\"_blank\"><svg  class=\"svg-icon text-[20px] mr-[8px] text-[20px] mr-[8px]\" aria-hidden=\"true\"><use  xlink:href=\"#icon-github\"></use></svg><h3 class=\"font-bold text-[18px] my-[4px]\"><span class=\"sk-text\" style=\"--fp:16.67%;--sp:83.33%;--lh:29.8368px;\">Vue3-h5-template</span></h3><svg  class=\"svg-icon text-[12px] ml-[5px] text-[12px] ml-[5px]\" aria-hidden=\"true\"><use  xlink:href=\"#icon-link\"></use></svg></a></div><div class=\"text-[14px] py-[2px] px-[10px] rounded-[4px] bg-[var(--color-block-background)] mt-[14px]\"><p class=\"my-[14px] leading-[24px]\"><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\"> 🌱 基于 Vue3 全家桶、TypeScript、Vite 构建工具,开箱即用的 H5 移动端项目基础模板 </span></p></div><div class=\"demo-main\"><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ ⚡ Vue3 + Vite5</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 🍕 TypeScript</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ ✨ Vant4 组件库</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 🌀 Tailwindcss 原子类框架</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 🍍 Pinia 状态管理</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 🌓 支持深色模式</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ Vue-router 4</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 支持 SVG 图标自动注册组件</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ vmin 视口适配</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ Axios 封装</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 打包资源 gzip 压缩</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 开发环境支持 Mock 数据</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ ESLint</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 首屏加载动画</span></span><!----></div><!----><!----><!----></div><div class=\"van-cell\"><!----><div class=\"van-cell__title\"><span><span class=\"sk-text\" style=\"--fp:20.83%;--sp:79.17%;--lh:26.5216px;\">✔ 开发环境调试面板</span></span><!----></div><!----><!----><!----></div></div></div></div>","pathname":"/"}}

重现操作

git clone https://github.com/yulimchen/vue3-h5-template.git
pnpm install
pnpm dev
浏览器 切换为手机模式
右键、检查、【Toggle device toolbar:Ctrl + Shift + M】、页面右下角,点击【点击生成骨架】

改动

F:\vue3-h5-template>git diff . ":!pnpm-lock.yaml"
diff --git a/index.html b/index.html
index 464b0ca..db29641 100644
--- a/index.html
+++ b/index.html
@@ -11,45 +11,7 @@
     <title>vue3-h5-template</title>
   </head>
   <body>
-    <div id="app">
-      <style>
-        html,
-        body,
-        #app {
-          height: 100%;
-          margin: 0px;
-          padding: 0px;
-          width: 100%;
-        }
-        .__spinner-container {
-          height: 100%;
-          display: flex;
-          flex-direction: column;
-          align-items: center;
-          justify-content: center;
-        }
-        .__spinner {
-          position: relative;
-          width: 68px;
-          height: 68px;
-          background-color: #41b883;
-          animation: cube-shadow-spinner 1.8s cubic-bezier(0.75, 0, 0.5, 1)
-            infinite;
-        }
-        @keyframes cube-shadow-spinner {
-          50% {
-            border-radius: 50%;
-            transform: scale(0.5) rotate(360deg);
-          }
-          100% {
-            transform: scale(1) rotate(720deg);
-          }
-        }
-      </style>
-      <div class="__spinner-container">
-        <div class="__spinner"></div>
-      </div>
-    </div>
+    <div id="app">__SKELETON_CONTENT__</div>
     <script type="module" src="/src/main.ts"></script>
     <% if (ENABLE_ERUDA === "true") { %>
     <script src="//cdn.jsdelivr.net/npm/eruda"></script>
diff --git a/package.json b/package.json
index e345b57..5d0f6a6 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
     "nprogress": "^0.2.0",
     "pinia": "^2.1.7",
     "vant": "^4.9.0",
+    "vite-plugin-auto-skeleton": "^1.1.0",
     "vue": "^3.4.27",
     "vue-router": "^4.3.2"
   },
diff --git a/src/main.ts b/src/main.ts
index e5afe39..74a05a4 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -9,9 +9,17 @@ import "./styles/tailwind.css";
 // svg icon
 import "virtual:svg-icons-register";

+import { initInject } from 'vite-plugin-auto-skeleton/client'
+import 'vite-plugin-auto-skeleton/skeleton.css' // 内置的骨架屏样式,可以自己重写
+
 import App from "./App.vue";
 import router from "./router";

+// 开发环境下才注入
+if (import.meta.env.DEV) {
+    setTimeout(initInject)
+}
+
 const app = createApp(App);
 app.use(store);
 app.use(router);
diff --git a/src/views/demo/index.vue b/src/views/demo/index.vue
index da725fe..7067bfa 100644
--- a/src/views/demo/index.vue
+++ b/src/views/demo/index.vue
@@ -1,5 +1,12 @@
 <script setup lang="ts" name="Demo">
-import { reactive } from "vue";
+import { reactive, onMounted, ref } from "vue";
+const loading = ref(true)
+  onMounted(() => {
+    // 模拟接口请求
+    setTimeout(() => {
+      loading.value = false
+    }, 1000)
+  })

 const contentList = reactive([
   "✔ ⚡ Vue3 + Vite5",
@@ -21,7 +28,9 @@ const contentList = reactive([
 </script>

 <template>
-  <div class="demo-content px-[12px]">
+  <div>
+    <div v-if="loading">__SKELETON_DEMO_CONTENT__</div>
+    <div data-skeleton-root="DEMO" v-else class="demo-content px-[12px]">
     <img
       class="block w-[120px] mx-auto mb-[20px] pt-[30px]"
       alt="Vue logo"
@@ -51,4 +60,6 @@ const contentList = reactive([
       <van-cell v-for="(item, idx) in contentList" :key="idx" :title="item" />
     </div>
   </div>
+  </div>
+  
 </template>
diff --git a/vite.config.ts b/vite.config.ts
index f8615ef..5073f00 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -11,6 +11,7 @@ import vueSetupExtend from "vite-plugin-vue-setup-extend";
 import viteCompression from "vite-plugin-compression";
 import { createHtmlPlugin } from "vite-plugin-html";
 import { enableCDN } from "./build/cdn";
+import { SkeletonPlaceholderPlugin, SkeletonApiPlugin } from "vite-plugin-auto-skeleton/vite"

 // 当前工作目录路径
 const root: string = process.cwd();
@@ -22,7 +23,9 @@ export default defineConfig(({ mode }) => {
   return {
     base: env.VITE_PUBLIC_PATH || "/",
     plugins: [
+      SkeletonPlaceholderPlugin(),
       vue(),
+      SkeletonApiPlugin(),
       vueJsx(),
       mockDevServerPlugin(),
       // vant 组件自动按需引入
@@ -68,6 +71,7 @@ export default defineConfig(({ mode }) => {
       }
     },
     build: {
+      cssCodeSplit: false,
       rollupOptions: {
         output: {
           chunkFileNames: "static/js/[name]-[hash].js",

F:\vue3-h5-template>
tangxiangmin commented 3 months ago

看起来是应该是svg图标的样式导致的页面样式异常,可以先手动将skeleton/content.json的中对应的svg代码移除试试。

这个插件的主要思路是为当前页面创建一段看起来可以用的骨架屏代码,部分需要特殊处理的样式,可以修改生成的骨架屏代码。

我晚点看一下处理svg图标的情况,这个自动解析标签为骨架屏标签的核心代码是很早之前的demo代码,可能有很多边界情况没有处理到,这个库本身也是作为一个实验进行尝试的,暂时不建议在生产环境中使用哦

tangxiangmin commented 3 months ago

看了下你的代码,应该是svg-icon这个组件内部,有css scoped的样式,这些标签上面的scopId限制了在骨架屏的时候无法使用对应的样式。

由于生产的骨架屏代码只会生成必要的类名和行类样式,大部分情况下会复用项目已定义的样式类,如果骨架屏代码无法应用对应的样式,就会出现上面截图中的样式错乱问题。

关于骨架屏样式无法在vue scoped css下生效的问题,我之前考虑过编写postcss插件,将用到的样式再复制一份到骨架屏的根节点下面,但是对生产环境的代码有侵入,这个思路不是很好。具体的想法可以看这个插件的开发文档vite插件实现骨架屏自动化中与样式相关的章节

最简单做法是使用原子类样式,由于原子类是全局生效的,就不会存在这个问题。

如果你有什么比较好的想法,也可以跟我讨论。

M69W commented 3 months ago

上面的样式手动改下还好 开发模式看着正常,编译后,如果网络差些,显示【__SKELETON_CONTENT__】就有些突兀; 原项目内的样式也被影响了。估计就是你提及的问题。