BACK
Featured image of post 分享一個實用的 Chrome 擴充功能 - Console Importer

分享一個實用的 Chrome 擴充功能 - Console Importer

介紹 Console Importer Chrome 擴充功能,讓開發者能夠在瀏覽器 Console 中輕鬆匯入 JavaScript 和 CSS 資源,提高開發效率和除錯體驗。

Chrome 線上應用程式商店 - Console Importer
Github - Console Importer

作為前端開發者,我們經常需要在瀏覽器 Console 中測試一些 JavaScript 函數庫或是 CSS 樣式。但要在 Console 中載入外部資源通常需要手動建立 <script><link> 標籤,過程相當繁瑣。

今天要分享的 Console Importer 這個 Chrome 擴充功能,能夠讓我們在 Console 中輕鬆匯入各種 JavaScript 和 CSS 資源,大幅提升開發效率。


什麼是 Console Importer?

Console Importer 是一個輕量級的 Chrome 擴充功能,它在瀏覽器的開發者工具 Console 中提供了一個全域函數 $i,讓開發者能夠快速匯入 JavaScript 函數庫和 CSS 樣式表。

這個工具特別適合用於:

  • 🔍 快速測試:在任何網站上測試新的 JavaScript 函數庫
  • 🎨 樣式調試:載入 CSS 框架來測試網頁外觀
  • 📚 學習探索:快速載入不同版本的函數庫進行比較
  • 🛠️ 除錯協助:在生產環境中臨時載入除錯工具

主要特色

  • 簡單易用:只需一行指令即可載入資源
  • 🌐 多種來源:支援 CDN、NPM 套件、直接 URL
  • 📦 版本控制:可指定特定版本的函數庫
  • 🎯 ES Module 支援:現代化的模組載入方式
  • 🔒 安全性:不會覆蓋現有的全域變數
  • 🔄 重整即重置:頁面重新整理後可輕鬆清除測試環境

Console Importer 的運作原理

Console Importer 的運作邏輯相當聰明,讓我們深入了解它是如何工作的:

1. 函數庫名稱識別與解析

Console Importer 會根據輸入的參數來決定從哪裡載入資源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 純函數庫名稱 → cdnjs
$i('jquery') 
// → https://cdnjs.cloudflare.com/ajax/libs/jquery/latest/jquery.min.js

// 含版本號 → unpkg
$i('[email protected]') 
// → https://unpkg.com/[email protected]/dist/jquery.min.js

// 完整 URL → 直接載入
$i('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js')

解析流程

  1. 檢查輸入是否為完整 URL(含 http://https://
  2. 如果不是 URL,檢查是否包含版本號(@ 符號)
  3. 根據結果選擇對應的 CDN 服務

2. 資源類型自動判斷

擴充功能會透過以下方式判斷資源類型:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// JavaScript 檔案判斷邏輯
function isJavaScript(url) {
  return url.endsWith('.js') || 
         url.includes('javascript') || 
         !url.endsWith('.css')
}

// CSS 檔案判斷邏輯  
function isCSS(url) {
  return url.endsWith('.css') || 
         url.includes('stylesheet')
}

3. 動態 DOM 元素建立

Console Importer 會在頁面中動態建立對應的 HTML 元素:

JavaScript 載入機制:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 建立 <script> 標籤
const script = document.createElement('script')
script.src = resolvedUrl
script.async = true
script.crossOrigin = 'anonymous'

// 載入完成的 Promise 處理
script.onload = () => resolve()
script.onerror = () => reject()

// 插入到 <head> 中
document.head.appendChild(script)

CSS 載入機制:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 建立 <link> 標籤
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = resolvedUrl
link.crossOrigin = 'anonymous'

// 載入狀態監聽
link.onload = () => resolve()
link.onerror = () => reject()

// 插入到 <head> 中
document.head.appendChild(link)

4. 重複載入防護機制

Console Importer 具有智能的重複載入檢查:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 內部維護的載入記錄
const loadedResources = new Set()

function $i(resource) {
  const resolvedUrl = resolveUrl(resource)
  
  // 檢查是否已經載入過
  if (loadedResources.has(resolvedUrl)) {
    console.log(`${resource} 已經載入過,跳過重複載入`)
    return Promise.resolve()
  }
  
  // 標記為已載入
  loadedResources.add(resolvedUrl)
  
  // 執行載入邏輯
  return loadResource(resolvedUrl)
}

5. ES Module 載入機制

對於 ES Module,Console Importer 使用現代的 import() 語法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
async function loadESModule(packageName) {
  // 使用 esm.run 作為 ES Module CDN
  const moduleUrl = `https://esm.run/${packageName}`
  
  try {
    // 動態 import
    const module = await import(moduleUrl)
    return module.default || module
  } catch (error) {
    throw new Error(`Failed to load ES module: ${packageName}`)
  }
}

頁面重整與資源重置機制

這是很多開發者關心的重要問題:當頁面重新整理後會發生什麼?

🔄 頁面重整後的行為

已載入的資源狀態

  • DOM 中的元素會被清除:透過 Console Importer 動態載入的 <script><link> 標籤會被移除
  • CSS 樣式會消失:由於 <link> 標籤被清除,所有載入的 CSS 樣式都會失效
  • JavaScript 變數會重置:所有透過 JavaScript 載入的全域變數都會被清除
  • Console Importer 記錄重置:內部的載入記錄會被清空
  • 🔄 完全重置環境:頁面會回到載入前的原始狀態

實際測試範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 第一次載入
$i('jquery')
console.log(typeof $) // "function"
console.log(document.querySelector('script[src*="jquery"]')) 
// <script src="https://cdnjs.cloudflare.com/.../jquery.min.js"></script>
// → script 標籤存在

// 頁面重整後...
console.log(typeof $) // "undefined" (變數被清除)
console.log(document.querySelector('script[src*="jquery"]')) 
// null
// → script 標籤也被清除了!需要重新載入

🚀 重整後的最佳實踐

方法 1:重新載入所需資源

1
2
3
4
5
6
7
8
9
// 重整後需要重新載入所有資源
$i('jquery') // 重新載入 jQuery

// 等待載入完成
setTimeout(() => {
  console.log(typeof $) // "function" - 重新載入成功
  console.log(document.querySelector('script[src*="jquery"]')) 
  // <script src="..."> - DOM 元素重新創建
}, 1000)

方法 2:檢查載入狀態

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 建立一個檢查函數
function ensureLibraryLoaded(libName, globalVar, callback) {
  if (typeof window[globalVar] !== 'undefined') {
    // 已經載入完成
    callback()
  } else {
    // 需要重新載入或等待
    $i(libName)
    const checkInterval = setInterval(() => {
      if (typeof window[globalVar] !== 'undefined') {
        clearInterval(checkInterval)
        callback()
      }
    }, 100)
  }
}

// 使用範例
ensureLibraryLoaded('jquery', '$', () => {
  console.log('jQuery 已準備就緒!')
  $('#myElement').hide()
})

方法 3:自動重載腳本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 建立一個自動重載的工具函數
function autoReload(libraries) {
  const reloadPromises = libraries.map(lib => {
    if (typeof lib.check === 'function' && !lib.check()) {
      console.log(`重新載入 ${lib.name}...`)
      return $i(lib.package)
    }
    return Promise.resolve()
  })
  
  return Promise.all(reloadPromises)
}

// 使用範例
const myLibraries = [
  { name: 'jQuery', package: 'jquery', check: () => typeof $ !== 'undefined' },
  { name: 'Lodash', package: 'lodash', check: () => typeof _ !== 'undefined' },
  { name: 'Moment', package: 'moment', check: () => typeof moment !== 'undefined' }
]

// 頁面載入後自動檢查並重載
autoReload(myLibraries).then(() => {
  console.log('所有函數庫都已準備就緒!')
})

⚠️ 需要注意的陷阱

1. CSS 樣式累積問題

1
2
3
4
5
6
7
8
9
// 重複載入 CSS 可能導致樣式重複
$i('https://cdn.tailwindcss.com') // 首次載入
// 頁面重整後...
$i('https://cdn.tailwindcss.com') // 可能會再次載入

// 解決方案:檢查是否已存在
if (!document.querySelector('link[href*="tailwindcss"]')) {
  $i('https://cdn.tailwindcss.com')
}

2. 版本衝突問題

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 重整前載入了舊版本
$i('[email protected]')

// 重整後想載入新版本
$i('[email protected]') // 可能會有兩個版本同時存在

// 解決方案:清理舊版本
function cleanOldScripts(pattern) {
  document.querySelectorAll(`script[src*="${pattern}"]`)
    .forEach(script => script.remove())
}

cleanOldScripts('jquery')
$i('[email protected]')

📋 重整檢查清單

開發時建議建立這樣的檢查流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 重整後的環境檢查
function checkEnvironment() {
  const checks = [
    { name: 'jQuery', test: () => typeof $ !== 'undefined' },
    { name: 'Lodash', test: () => typeof _ !== 'undefined' },
    { name: 'Chart.js', test: () => typeof Chart !== 'undefined' }
  ]
  
  console.group('🔍 環境檢查')
  checks.forEach(check => {
    const status = check.test() ? '✅' : '❌'
    console.log(`${status} ${check.name}`)
  })
  console.groupEnd()
}

// 使用
checkEnvironment()

這樣可以讓你快速了解重整後哪些函數庫需要重新載入!


安裝方式

方法一:Chrome 線上應用程式商店安裝

  1. 前往 Chrome 線上應用程式商店
  2. 點擊「加到 Chrome」按鈕
  3. 確認安裝權限
  4. 安裝完成後,打開任何網頁的開發者工具即可使用
🌐 新分頁使用注意:
重要:在完全新的空白分頁(如 chrome://newtab/about:blank)中,$i 函數無法正常掛載,這是因為 Chrome 擴充功能需要在實際的網頁環境中才能注入腳本。

解決方案:請先導航到任何一個實際的網站(如 https://www.google.comhttps://github.com 等),然後打開 Console,此時 $i 函數就會正常可用了。

方法二:手動安裝(開發者模式)

1
2
3
4
5
6
7
8
9
# clone 專案
git clone https://github.com/pd4d10/console-importer.git
cd console-importer

# 安裝依賴
pnpm install

# 打包擴充功能
pnpm build

然後在 Chrome 的擴充功能管理頁面啟用「開發者模式」,載入 build 資料夾即可。


基本使用方法

安裝完成後,在任何網頁上打開開發者工具(F12),切換到 Console 標籤,就可以開始使用 $i 函數了。

📋 使用前檢查:
在新分頁中,請先確認 Console Importer 擴充功能是否正常運作。可以在 Console 輸入 typeof $i,如果回傳 "function" 表示擴充功能已正常載入;如果回傳 "undefined" 則需要先安裝或啟用擴充功能。
🌐 新分頁使用注意:
重要:在完全新的空白分頁(如 chrome://newtab/about:blank)中,$i 函數通常無法正常掛載。這是因為 Chrome 擴充功能需要在實際的網頁環境中才能注入腳本。

解決方案:請先導航到任何一個實際的網站(如 https://www.google.comhttps://github.com 等),然後打開 Console,此時 $i 函數就會正常可用了。

載入 JavaScript 函數庫

1. 載入熱門函數庫

1
2
3
4
5
6
7
8
// 載入最新版本的 jQuery
$i('jquery')

// 載入最新版本的 Lodash
$i('lodash')

// 載入 Bootstrap JavaScript
$i('bootstrap')

2. 指定版本載入

1
2
3
4
5
6
7
8
// 載入 jQuery 2.x 版本
$i('jquery@2')

// 載入指定版本的 Vue.js
$i('[email protected]')

// 載入特定版本的 React
$i('[email protected]')

3. 直接載入 URL

1
2
3
4
5
// 從 CDN 載入 jQuery
$i('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js')

// 載入自定義的 JavaScript 檔案
$i('https://example.com/custom-script.js')

載入 CSS 樣式表

1
2
3
4
5
6
7
8
// 載入 Bootstrap CSS
$i('https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css')

// 載入 Font Awesome
$i('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css')

// 載入自定義樣式
$i('https://example.com/custom-styles.css')

進階功能

ES Module 載入

現代 JavaScript 開發大量使用 ES Module,Console Importer 提供了 $i.esm 方法來載入 ES Module:

1
2
3
4
5
6
7
8
// 載入 D3.js ES Module
const d3 = await $i.esm('d3')

// 載入指定版本的 ES Module
const d3v7 = await $i.esm('d3@7')

// 使用載入的模組
d3.select('body').append('h1').text('Hello D3!')
💡 ES Module 的優勢:
ES Module 載入方式不會將變數加入到全域作用域中,能夠更好地控制副作用的範圍。

指定 CDN 來源

如果需要從特定的 CDN 載入資源,可以使用以下專用方法:

1
2
3
4
5
// 從 unpkg 載入
$i.unpkg('[email protected]')

// 從 cdnjs 載入
$i.cdnjs('jquery')

實際應用範例

範例:快速測試 Chart.js

假設我們想在某個網站上測試圖表功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 載入 Chart.js
$i('chart.js')

// 等待載入完成後,建立一個簡單的圖表
setTimeout(() => {
  // 在頁面中建立 canvas 元素
  const canvas = document.createElement('canvas')
  canvas.id = 'myChart'
  canvas.width = 400
  canvas.height = 200
  document.body.appendChild(canvas)
  
  // 建立圖表
  const ctx = document.getElementById('myChart').getContext('2d')
  new Chart(ctx, {
    type: 'bar',
    data: {
      labels: ['一月', '二月', '三月', '四月', '五月'],
      datasets: [{
        label: '銷售額',
        data: [12, 19, 3, 5, 2],
        backgroundColor: 'rgba(54, 162, 235, 0.2)',
        borderColor: 'rgba(54, 162, 235, 1)',
        borderWidth: 1
      }]
    },
    options: {
      scales: {
        y: {
          beginAtZero: true
        }
      }
    }
  })
}, 2000)

範例:載入 Tailwind CSS 進行樣式測試

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 載入 Tailwind CSS
$i('https://cdn.tailwindcss.com')

// 等待載入完成後,為頁面元素加上 Tailwind 樣式
setTimeout(() => {
  // 選取頁面中的標題元素
  const headings = document.querySelectorAll('h1, h2, h3')
  headings.forEach(heading => {
    heading.className = 'text-3xl font-bold text-blue-600 mb-4'
  })
  
  // 為按鈕加上樣式
  const buttons = document.querySelectorAll('button, .btn')
  buttons.forEach(button => {
    button.className = 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'
  })
}, 1000)

範例:使用 Lodash 進行數據處理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 載入 Lodash
$i('lodash')

// 等待載入完成後使用 Lodash 功能
setTimeout(() => {
  // 模擬一些數據
  const users = [
    { name: 'Alice', age: 25, city: 'Taipei' },
    { name: 'Bob', age: 30, city: 'Kaohsiung' },
    { name: 'Charlie', age: 35, city: 'Taipei' },
    { name: 'Diana', age: 28, city: 'Taichung' }
  ]
  
  // 使用 Lodash 進行數據操作
  console.log('按年齡分組:', _.groupBy(users, 'age'))
  console.log('平均年齡:', _.meanBy(users, 'age'))
  console.log('台北的使用者:', _.filter(users, { city: 'Taipei' }))
  console.log('排序後的使用者:', _.sortBy(users, 'age'))
  
}, 1000)

範例:ES Module 載入 Day.js 進行日期處理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 使用 ES Module 方式載入 Day.js
const dayjs = await $i.esm('dayjs')

// 直接使用,不會污染全域變數
console.log('現在時間:', dayjs().format('YYYY-MM-DD HH:mm:ss'))
console.log('一週後:', dayjs().add(7, 'day').format('YYYY-MM-DD'))
console.log('相對時間:', dayjs().fromNow())

// 載入 Day.js 插件
const relativeTime = await $i.esm('dayjs/plugin/relativeTime')
dayjs.extend(relativeTime)
console.log('三天前:', dayjs().subtract(3, 'day').fromNow())

常見問題與解決方案

問題:$i is not defined 錯誤

現象:在 Console 輸入 $i("jquery") 時出現 Uncaught ReferenceError: $i is not defined

可能原因與解決方案

原因:擴充功能未安裝或啟用

  1. 確認已從 Chrome 線上應用程式商店 安裝擴充功能
  2. 檢查擴充功能是否已啟用:進入 chrome://extensions/ 確認 Console Importer 狀態為「已啟用」
  3. 重新載入頁面後再次嘗試
  4. 如果仍有問題,嘗試重新安裝擴充功能

原因:在不支援的頁面中使用

最常見情況:在新分頁或特殊頁面中無法使用 $i

不支援的頁面類型

  • chrome://newtab/(Chrome 新分頁)
  • about:blank(空白頁面)
  • chrome://extensions/(擴充功能頁面)
  • chrome://settings/(設定頁面)
  • 某些內部頁面或受限頁面

解決方案

1
2
3
4
5
6
7
8
// ❌ 在新分頁中嘗試使用(會失敗)
// 打開 chrome://newtab/ 然後嘗試
typeof $i // "undefined"

// ✅ 導航到實際網站後使用
// 前往 https://www.google.com 或任何網站
typeof $i // "function"
$i('jquery') // 正常運作

快速測試步驟

  1. 打開新分頁
  2. 前往任何網站(推薦:https://httpbin.orghttps://example.com
  3. 開啟開發者工具 (F12)
  4. 在 Console 輸入 typeof $i 檢查是否為 "function"

問題:$i 函數不起作用

原因:某些網站(如 Google Inbox)已經使用了 $i 作為全域變數,Console Importer 不會覆蓋現有變數。

解決方案:使用 console.$i 替代:

1
2
// 在有衝突的網站上使用
console.$i('jquery')

問題:資源載入失敗

原因:某些網站(如 GitHub)有嚴格的內容安全政策(CSP),會阻止載入外部資源。

錯誤訊息範例

1
2
Refused to connect to 'https://api.cdnjs.com/libraries?search=jquery' 
because it violates the following Content Security Policy directive

解決方案

  1. 嘗試在其他沒有嚴格 CSP 的網站上使用
  2. 使用本地檔案或內網資源
  3. 臨時停用 CSP(僅適用於開發環境)

問題:載入後無法立即使用

原因:網路載入需要時間,特別是大型函數庫。

解決方案:使用 setTimeout 或監聽載入事件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$i('jquery')

// 方法 1:使用 setTimeout
setTimeout(() => {
  $('#myElement').hide()
}, 2000)

// 方法 2:輪詢檢查
const checkLoaded = setInterval(() => {
  if (typeof $ !== 'undefined') {
    clearInterval(checkLoaded)
    $('#myElement').hide()
  }
}, 100)

與其他工具的比較

Console Importer vs 手動建立檔案與內容

傳統方式

1
2
3
4
5
6
7
8
// 手動建立 script 標籤
const script = document.createElement('script')
script.src = 'https://code.jquery.com/jquery-3.7.1.min.js'
document.head.appendChild(script)
script.onload = () => {
  // 使用 jQuery
  $('body').addClass('loaded')
}

Console Importer

1
2
// 一行搞定
$i('jquery')

Console Importer vs 其他瀏覽器擴充功能

功能Console Importer其他擴充功能
簡潔性⭐⭐⭐⭐⭐⭐⭐⭐
版本控制⭐⭐⭐⭐⭐⭐⭐
ES Module⭐⭐⭐⭐⭐
檔案大小中等
學習成本極低中等

最佳實踐建議

效能考量

1
2
3
4
5
// ❌ 避免載入過大的函數庫影響頁面效能
$i('entire-ui-framework@latest')

// ✅ 只載入需要的部分
$i('lodash/debounce')

版本管理

1
2
3
4
5
// ❌ 不指定版本可能導致不一致
$i('react')

// ✅ 指定明確版本確保穩定性
$i('[email protected]')

安全性

1
2
3
4
5
// ❌ 不要載入不信任的來源
$i('https://suspicious-site.com/malicious.js')

// ✅ 使用知名 CDN
$i('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js')

結語

Console Importer 是一個簡單卻非常實用的開發工具,它讓我們能夠在瀏覽器 Console 中快速測試各種 JavaScript 函數庫和 CSS 樣式。無論是快速原型設計、除錯、或是學習新技術,這個工具都能大幅提升我們的開發效率。

適合使用的場景

  • 🔍 快速測試新的 JavaScript 函數庫
  • 🎨 在現有網站上測試不同的 CSS 框架
  • 📚 學習和比較不同版本的函數庫
  • 🛠️ 在生產環境中進行臨時除錯
  • 🚀 快速建立概念驗證(PoC)

如果你是前端開發者,我強烈推薦安裝這個擴充功能到你的 Chrome 瀏覽器中。它會成為你開發工具箱中不可或缺的一部分。

立即安裝:Chrome 線上應用程式商店 - Console Importer

⚠️ 注意事項:
雖然 Console Importer 非常方便,但請記住只在開發和測試環境中使用。在生產環境中隨意載入外部資源可能會帶來安全風險和效能問題。

相關資源

希望這篇文章對您有幫助!如果您有任何問題或建議,歡迎在下方留言討論。🚀


comments powered by Disqus