我试图在Azure函数中使用外部javascript ( javascript/node.js风味)。由于外部javascript (我需要使用kendo)依赖于一个DOM和一个窗口,所以我尝试使用JSDOM (但如果有更好/更简单的替代方法,则不必使用JSDOM )。
这是我所拥有的一个简单的例子:
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var html = '<!DOCTYPE html>'
+ '<html>'
+ '<head>'
+ '<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>'
+ '<script src="https://kendo.cdn.telerik.com/2019.2.514/js/kendo.all.min.js"></script>'
+ '</head>'
+ '<body>'
+ '<script>'
+ 'var myDiv = document.createElement("div");'
+ 'myDiv.innerHTML = "Hello World";'
+ 'document.body.appendChild(myDiv);'
+ '</script>'
+ '</body>'
+ '</html>'
;
var jsdom = require('jsdom');
const { JSDOM } = jsdom;
const dom = new JSDOM(html, {
runScripts: "dangerously",
resources: "usable"
});
var test = dom.serialize();
context.log(test);
context.res = {
body: test
};
};
在运行此Azure函数时,应该包括jquery和kendo,并创建包含"Hello“的div。不过,这不管用。
创建的脚本只有在我注释掉
+ '<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>'
+ '<script src="https://kendo.cdn.telerik.com/2019.2.514/js/kendo.all.min.js"></script>'
或
resources: "usable"
但是,我不能使用jquery和kendo。
根据这个jsdom 文档,参数资源:“可用”应该能起作用,但是由于某种原因,它不能工作。
我使用的是"jsdom":"^15.1.1“
UPDATE:我尝试了一个解决办法,添加这样的脚本:
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var html = '<!DOCTYPE html>'
+ '<html>'
+ '<head>'
+ '</head>'
+ '<body>'
+ '<script>'
+ 'var myDiv = document.createElement("div");'
+ 'myDiv.innerHTML = "Hello World";'
+ 'document.body.appendChild(myDiv);'
+ 'var scriptTag = document.createElement("script");'
+ 'scriptTag.innerHTML = window.jqueryString;'
+ 'document.head.appendChild(scriptTag);'
+ '</script>'
+ '</body>'
+ '</html>'
;
var jsdom = require('jsdom');
const { JSDOM } = jsdom;
var fs = require("fs");
global.jqueryString = fs.readFileSync(__dirname + '//jquery.js').toString();
//context.log(jqueryString);
const dom = new JSDOM(html, {
runScripts: "dangerously"
});
var test = dom.serialize();
context.log(test);
context.res = {
body: test
};
};
这是在头中添加一个脚本标记,但是innerHTML是“未定义的”,而不是jqueryString。在JSDOM之外(请参阅注释行),日志记录jqueryString按预期显示jquery.js的内容。但是在JSDOM内部,这个变量似乎不可用。如何将jqueryString传递给JSDOM?
发布于 2019-07-01 04:16:07
在@PeterPan的输入下,我成功地使用带有基于码头的Azure函数的木偶师解决了我的问题。
基于Init码头的FunctionApp:
func init MyFunctionProj --docker
(选择->节点-> javascript)
编辑MyFunctionProj\Dockerfile以使用estruyf/azure-功能-节点-傀儡和fs:
FROM estruyf/azure-function-node-puppeteer
RUN npm i fs
COPY . /home/site/wwwroot
将fs添加到MyFunctionProj\package.json中的依赖项:
"dependencies": {
"fs": "0.0.1-security"
}
创建HttpTrigger函数:
cd MyFunctionProj
func new --name MyHttpTrigger --template "HttpTrigger"
准许行使职能:
在"authLevel": "anonymous"
中设置MyFunctionProj\MyHttpTrigger\function.json (原因见这里。)
创建MyFunctionProj\MyHttpTrigger\content.html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>ContentHtml</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.2.514/js/kendo.all.min.js"></script>
</head>
<body>
<script>
$(document).ready(function() {
var myComputationResult = .... // use included scripts to perform computation
$("#resultData").html(JSON.stringify(myComputationResult));
});
</script>
<div id="resultData"></div>
</body>
</html>
在MyFunctionProj\MyHttpTrigger\index.js中编辑功能逻辑(基于这):
const puppeteer = require('puppeteer');
const fs = require("fs");
module.exports = async (context, req) => {
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox'
]
});
var contentHtml = fs.readFileSync(__dirname + '//content.html', 'utf8');
const page = await browser.newPage();
await page.goto(`data:text/html,${contentHtml}`, { waitUntil: 'networkidle2' });
const resultData = await page.evaluate(() => document.querySelector('#resultData').innerHTML);
await browser.close();
context.res = {
// status: 200, /* Defaults to 200 */
body: `Result: ${resultData}`
};
};
建立码头形象:
docker build --tag <docker-id>/mydockerimage:v1.0.0 .
运行码头图像:
docker run -p 8080:80 -it <docker-ID>/mydockerimage:v1.0.0
在浏览器中测试本地函数图像:
http://localhost:8080/api/MyHttpTrigger
将图像推送到码头枢纽:
docker login --username <docker-id>
docker push <docker-id>/mydockerimage:v1.0.0
创建一个新的Azure功能在线和使用图像从码头集线器描述的这里。
发布于 2019-06-27 20:34:12
我仔细检查了jsdom
节点包,然后我发现Loading subresources
功能需要一个无头浏览器,比如通过karma
的无头浏览器。但是,由于使用了Win32k.sys (User32/GDI32) Restrictions
of Azure Web App sandbox
,在上,它将永远无法正常工作,因为无头浏览器需要GDI
支持。
因此,我建议您需要将您的函数迁移到Linux函数(它基于Docker ),通过Azure Functions Core Tools
重新构建它,就像官方文档Create your first function hosted on Linux using Core Tools and the Azure CLI (preview)
说的那样。或者您必须使用Windows,Azure Windows VM将是您的最佳选择。
希望能帮上忙。
https://stackoverflow.com/questions/56753243
复制