Skip to content

Instantly share code, notes, and snippets.

@tokisakiyuu
Last active August 12, 2023 16:01
Show Gist options
  • Save tokisakiyuu/0a59c84f49e24673c7e0403920074fe5 to your computer and use it in GitHub Desktop.
Save tokisakiyuu/0a59c84f49e24673c7e0403920074fe5 to your computer and use it in GitHub Desktop.
Simple solution for reuse external script in tampermonkey

示例 index.html:

<html lang="zh-cn">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <title>Nano Require Example</title>
  <!-- @document-start inserts  -->
  <script src="./script-b.js"></script>
  <script src="./script-a.js"></script>
</head>
<body>
  Open Console check out result of execution.
</body>
</html>

a、b 两个脚本的开头都要包含一份完整的 nano-require.js ,这让两个脚本各自的依赖可以在系统范围内被重用,并且不需要关心 a、b 的执行的先后顺序。

使用模块导入

NR([
  "https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js,
  "https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"
"]).then(doSomething)
((gloabl) => {
/**
* Like require function in the commonjs, but return a promise.
* @param {string[]} urls An array of module url
*/
function nanoRequire(urls) {
// exclude already loaded modules
urls = urls.filter(url => !gloabl.NR_MODULE_MAP[url] || gloabl.NR_MODULE_MAP[url] !== 'loaded')
// hold current loading state of the module, so prevent others from fetch same module again.
urls.forEach(url => { gloabl.NR_MODULE_MAP[url] = 'loading' })
return Promise.allSettled(urls.map(url => fetchModule(url)))
.then(replies => {
replies.forEach((result, index) => {
if (result.status == 'fulfilled') {
gloabl.NR_MODULE_MAP[urls[index]] = 'loaded'
} else {
gloabl.NR_MODULE_MAP[urls[index]] = 'error'
throw result.reason
}
})
})
}
/**
* @param {string} url module's url
*/
function fetchModule(url) {
return new Promise((resolve, reject) => {
const script = gloabl.document.createElement('script')
script.src = url
script.onload = resolve
script.onerror = () => reject(new Error(`fetch module "${url}" failed`))
gloabl.document.head.appendChild(script)
})
}
!gloabl.NR && (gloabl.NR = nanoRequire)
// Hold loaded module and its state.
!gloabl.NR_MODULE_MAP && (gloabl.NR_MODULE_MAP = [])
})(window)
// all code in nano-require.js put here...
function doSomethingA() {
console.log('i am "script-a" using jq', jQuery)
}
NR(["https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"]).then(doSomethingA)
// all code in nano-require.js put here...
function doSomethingB() {
console.log('i am "script-b" using jq and react', jQuery, React)
}
NR([
"https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js",
"https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"
]).then(doSomethingB)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment