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') {