[英]Implementation of a client-side 'require' function compatible with node.js
決定將我所有的 Javascript 庫實現為與 node.js 兼容的模塊后,我現在已經將一個簡單的“要求”function 放在一起,以便在事物的客戶端使用。 我確實意識到已經有很多非常好的實現,但大多數看起來相當笨拙,所以我只是選擇 go 與“自己動手”的方法。
這是我的“require.js”文件:
/*
A client-side script loading class designed to be compatible with node.js
*/
function require(filename)
{
try
{
var
script = null,
ajax = new XMLHttpRequest(),
index = filename.toLowerCase().indexOf('.js');
if(index <= 0 || index != filename.length - 3)
filename += '.js';
ajax.onload = function()
{
script = this.responseText;
};
ajax.open('GET', filename, false);
ajax.send();
return _isolate_script_(script);
}
catch(error)
{
return null;
}
}
function _isolate_script_(_script_)
{
return (new Function
(
'var exports = {}, module = {exports : null}; '
+ _script_ +
'; return module.exports || exports;'
)).call();
}
示例模塊('example.js'):
/*
Example of a multiple-class export file
*/
exports.metallic = function(value)
{
return (Math.sqrt(4 + value * value) + value) / 2;
}
exports.inverse_metallic = function(value)
{
return exports.metallic(-value);
}
模塊使用者('main.js')的示例:
function main()
{
var
example = require('example');
if(example != null)
{
var
value = Math.floor(Math.random() * 100) + 1;
alert
(
'example.metallic(' + value + ') = ' + example.metallic(value)
+ '\n' +
'example.inverse_metallic(' + value + ') = ' + example.inverse_metallic(value)
);
}
else
alert('Error: cannot load "example"');
}
最后,調用我們的頁面邏輯的基本 HTML 文件:
<!DOCTYPE html>
<html>
<head>
<script src = 'require.js'></script>
<script src = 'main.js'></script>
</head>
<body onload = "main()"></body>
</html>
所以我的具體問題只是我是否正確地實現了所有東西,而且框架和用例是否看起來足夠干凈?
看來您正在嘗試重新實現Browserify :
瀏覽器沒有定義require方法,但是Node.js有。 使用Browserify可以編寫使用require的代碼,就像在Node中使用它一樣。
如果您想自己實現類似的功能,請查看Browserify源代碼。
我將自己回答。
主要問題是,較舊的瀏覽器有時會因同步ajax請求而凍結。 簡單地在自己的線程中啟動整個“ main”功能似乎是一個很好的解決方案。 也就是說,如果在加載腳本時出現一些不可預見的問題,則頁面本身可能沒有響應,但是瀏覽器至少應不受影響。 換句話說,與此類似:
<!DOCTYPE html>
<html>
<head>
<script src = 'require.js'></script>
<script src = 'main.js'></script>
</head>
<body onload = "setInterval(main)"></body>
</html>
關於吞吐量,我現在已經用大量數據(〜100 MB)對其進行了測試,對於代碼是通過腳本標簽還是通過ajax調用加載,似乎對性能沒有太大影響。 所有主要瀏覽器都在兩種不同的操作系統上運行,結果幾乎相同。 因此,除非我看到令人信服的證據,否則我將假設這是規則,而不是例外。
話雖這么說,我當然仍然對可能的任何評論或批評持開放態度。
如果您還想要模塊緩存,請嘗試以下操作:
let parent = "";
let cache = {};
/**
* Load a JavaScript text synchronously.
*
* @param url The url.
*/
function cludge(url) {
/* resolve and check */
if (parent !== "")
url = new URL(url, parent).href;
let map = cache[url];
if (map !== undefined)
return map;
map = {};
cache[url] = map;
/* load and execute */
let back = parent;
try {
parent = url;
let request = new XMLHttpRequest();
request.open('GET', url, false);
request.send();
let fun = new Function("exports", "require", request.responseText);
fun(map, cludge);
} finally {
parent = back;
}
return map;
}
但是名稱解析不像 nodejs 那樣復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.