From 6ae085ff2eb4b489be35c3661aec8c0efb687e59 Mon Sep 17 00:00:00 2001 From: redhoodsu Date: Wed, 4 Sep 2024 19:40:15 +0800 Subject: [PATCH] release: v1.1.0 --- CHANGELOG.md | 4 ++ index.html | 5 +- package.json | 2 +- src/back.js | 167 ++++++++++++++++++++++++++++++++++++++++++++-- src/index.js | 4 +- webpack.config.js | 7 +- 6 files changed, 180 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b011c4..2dc99fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.1.0 (4 Sep 2024) + +* feat: force dev mode + ## v1.0.1 (16 Aug 2024) * fix: initial theme not correct diff --git a/index.html b/index.html index c85d474..1df3932 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> Eruda-vue - +
{{ message }}
@@ -25,6 +25,9 @@ diff --git a/package.json b/package.json index 05b2060..2b6dbc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eruda-vue", - "version": "1.0.1", + "version": "1.1.0", "main": "eruda-vue.js", "description": "Eruda plugin for Vue", "files": [ diff --git a/src/back.js b/src/back.js index 66a0103..bca630e 100644 --- a/src/back.js +++ b/src/back.js @@ -1,15 +1,19 @@ -import { installHook } from '@back/hook' -import { initBackend } from '@back' +import { installHook as _installHook } from '@back/hook' import { Bridge } from '@utils/bridge' import { SharedData } from '@utils/shared-data' import createUrl from 'licia/createUrl' import devtools from 'raw-loader!./devtools.txt' -installHook(window) - let theme = 'auto' let shareDataLoaded = false +export function installHook() { + if (window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { + return + } + _installHook(window) +} + export function initDevtools(iframe) { const bridge = new Bridge({ listen(fn) { @@ -31,7 +35,9 @@ export function initDevtools(iframe) { shareDataLoaded = true setTheme(theme) }) - initBackend(bridge) + import('@back').then(({ initBackend }) => { + initBackend(bridge) + }) const devtoolsSrc = createUrl(devtools, { type: 'application/javascript' }) @@ -62,3 +68,154 @@ export function setTheme(value) { SharedData.theme = value } } + +// Modified from vue-devtools +export function forceEnable() { + if (!window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { + return + } + + let delay = 1000 + let detectRemainingTries = 10 + + function runDetect() { + // Method 1: Check Nuxt.js + const nuxtDetected = !!(window.__NUXT__ || window.$nuxt) + + if (nuxtDetected) { + let Vue + + if (window.$nuxt) { + Vue = window.$nuxt.$root && window.$nuxt.$root.constructor + } + + crack({ + devtoolsEnabled: + (Vue && Vue.config.devtools) || + (window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && + window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled), + vueDetected: true, + nuxtDetected: true, + }) + + return + } + + // Method 2: Check Vue 3 + const vueDetected = !!window.__VUE__ + if (vueDetected) { + crack({ + devtoolsEnabled: + window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && + window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled, + vueDetected: true, + }) + + return + } + + // Method 3: Scan all elements inside document + const all = document.querySelectorAll('*') + let el + for (let i = 0; i < all.length; i++) { + if (all[i].__vue__) { + el = all[i] + break + } + } + if (el) { + let Vue = Object.getPrototypeOf(el.__vue__).constructor + while (Vue.super) { + Vue = Vue.super + } + crack({ + devtoolsEnabled: Vue.config.devtools, + vueDetected: true, + }) + return + } + + if (detectRemainingTries > 0) { + detectRemainingTries-- + setTimeout(() => { + runDetect() + }, delay) + delay *= 5 + } + } + + setTimeout(() => { + runDetect() + }, 100) +} + +// https://github.com/hzmming/vue-force-dev +function crack(data) { + if (data.devtoolsEnabled) { + return + } + + // Nuxt.js + if (data.nuxtDetected) { + let Vue + + if (window.$nuxt) { + Vue = window.$nuxt.$root && window.$nuxt.$root.constructor + } + + // Vue 2 + if (Vue) { + crackVue2(Vue) + } else { + // Vue 3.2.14+ + crackVue3() + } + } + // Vue 3 + else if (window.__VUE__) { + crackVue3() + } + // Vue 2 + else { + crackVue2() + } +} + +function crackVue2(Vue) { + if (!Vue) { + const app = getVueRootInstance(2) + if (!app) return false // Vue may not be finished yet + Vue = Object.getPrototypeOf(app).constructor + while (Vue.super) { + Vue = Vue.super + } + } + + const devtools = window.__VUE_DEVTOOLS_GLOBAL_HOOK__ + Vue.config.devtools = true + devtools.emit('init', Vue) +} + +function crackVue3() { + const app = getVueRootInstance(3) + if (!app) return false // Vue may not be finished yet + const devtools = window.__VUE_DEVTOOLS_GLOBAL_HOOK__ + devtools.enabled = true + const version = app.version + devtools.emit('app:init' /* APP_INIT */, app, version, { + Fragment: Symbol.for('v-fgt'), + Text: Symbol.for('v-txt'), + Comment: Symbol.for('v-cmt'), + Static: Symbol.for('v-stc'), + }) +} + +function getVueRootInstance(version) { + const signProperty = version === 2 ? '__vue__' : '__vue_app__' + const all = document.querySelectorAll('*') + for (let i = 0; i < all.length; i++) { + if (all[i][signProperty]) { + return all[i][signProperty] + } + } +} diff --git a/src/index.js b/src/index.js index 950a7ad..dd73371 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -const { initDevtools, setTheme } = require('./back') +const { initDevtools, setTheme, installHook, forceEnable } = require('./back') module.exports = function (eruda) { let { evalCss } = eruda.util @@ -14,6 +14,8 @@ module.exports = function (eruda) { $el.html('') const iframe = $el.find('.eruda-vue-devtools').get(0) + installHook() + forceEnable() initDevtools(iframe) setTheme(this._getTheme()) diff --git a/webpack.config.js b/webpack.config.js index c3f0454..ae4279f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -89,7 +89,12 @@ module.exports = (env, argv) => { }, ], }, - plugins: [new webpack.BannerPlugin(banner)], + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + new webpack.BannerPlugin(banner) + ], } if (argv.mode === 'production') {