Javascript模块在浏览器中不起作用?

Posted

技术标签:

【中文标题】Javascript模块在浏览器中不起作用?【英文标题】:Javascript module not working in browser? 【发布时间】:2019-02-07 22:10:44 【问题描述】:

好的,我查看了这个网站并找到了几个不同的答案,但没有一个对我有用。 基本上有一个 js 文件,其中包含许多功能以及应用程序的主要代码。我想将我所有的函数移动到另一个 js 文件中,以便我可以稍微清理一下我的代码。我对 js 很陌生,但我知道在 python 中它就像说“import (module) as (nickname) from (path)”一样简单

无论如何,假设我的 functions.js 模块中有一个名为 show message 的函数。

export function show_message()
    alert("Hello");

然后我在我的 main.js 文件的顶部做了

import  show_message  from './functions.js'
//I have also tried to import like this:
import * as func from './functions.js'

//And then I call it
show_message();
//I have also tried
func.show_message();

我知道这很简单,但正如我所说的,我到处都看到了不同的答案,但没有一个对我有用。我正在使用 Firefox 顺便说一句。我还在控制台中收到一个错误,说我的导入声明需要在我的模块的顶部,我通过在我的 html 链接中指定类型(脚本 src="/static/main.js" type="模块”) 错误消失了,但现在说“同源策略不允许读取文件(路径)处的远程资源(原因:cors 请求不是 HTTP)。”

另一个错误是“此文档中不允许模块源 URI”。

这让我觉得我的导入语法可能是正确的,而错误在我的 HTML 代码中?

感谢任何帮助。

【问题讨论】:

我知道这是一个老问题,但对于其他搜索的人来说:这个资源有帮助吗?不确定您尝试过哪些方法***.com/questions/5797852/… 你试过func.show_message();吗?鉴于您使用的是import * as func from './functions.js' 这是一个 CORS 相对路径问题,不是导入问题。 javascript 中没有“导入”和“导出”之类的东西。如果您正在使用其他库,请添加其他标签。 ***.com/a/950146/1675954 就错误而言。模块源被禁止,禁用/卸载你的扩展 【参考方案1】:
function show_message()
    alert("Hello");


export  show_message ;

import  show_message  from './functions'

我认为这应该可以解决问题。这是一种命名的导出/导入技术。如果您愿意,可以在此名称下找到更多信息。

【讨论】:

【参考方案2】:

您可能想改用broswerify。它允许您编写 NodeJS 样式的模块,然后将它们编译成单个浏览器友好的 JavaScript 文件,从而让您获得仅加载单个文件的所有性能优势。这也意味着您可以轻松地在服务器端和客户端使用相同的代码。

如果您想坚持使用单独的文件,那么您似乎一切顺利。与常规 JavaScript 文件不同,模块受跨域资源共享 (CORS) 限制。它们必须从同一来源加载,并且不能从本地文件系统加载。如果您从本地文件系统加载它们,请将它们移动到服务器。如果您已经将它们托管在服务器上,请将 Access-Control-Allow-Origin: * 标头添加到为模块文件提供服务的响应中。

更多陷阱和解决方案here 和here。

【讨论】:

【参考方案3】:

在您用于在浏览器中加载js的脚本标签上,您需要添加属性

type="模块"

它将如下所示:

<script type="module">
  import addTextToBody from './utils.mjs';

  addTextToBody('Modules are pretty cool.');
</script>

utils.mjs:

export function addTextToBody(text) 
  const div = document.createElement('div');
  div.textContent = text;
  document.body.appendChild(div);

这是在你没有使用 webpack 之类的打包工具并直接在浏览器中工作的情况下。

代码来源:https://jakearchibald.com/2017/es-modules-in-browsers/

【讨论】:

【参考方案4】:

JavaScript 有模块很长时间了。但是,它们是通过库实现的,而不是内置于语言中,即您无法将这些模块的一部分导入或导出到您的 js 文件中(需要加载整个库)。 ES6 是 JavaScript 首次内置模块。

有关 ES 模块的更多信息,请参考Here。

但情况发生了变化,ES 模块现在可以在浏览器中使用!他们在……

Safari 10.1+、Chrome 61+、Firefox 60+、Edge 16+ 等。

现在,您需要使用新的扩展名 .mjs 创建您的 JS 文件,例如,

// utils.mjs
export function addTextToBody(text) 
  const div = document.createElement('div');
  div.textContent = text;
  document.body.appendChild(div);

然后,您可以将该文件导入到您的 html 页面中,例如,

<script type="module">
 import addTextToBody from './utils.mjs';

 addTextToBody('Modules are pretty cool.');
</script>

有关在浏览器中使用 ES 模块的更多信息,请参阅Here。

【讨论】:

【参考方案5】:

考虑通过this url 某些扩展可能会导致模块加载出现问题:

This blog 可能是您所期望的答案。

您应该首先检查浏览器是否接受 type="module",如果不喜欢,请使用后备:

<script type="module" src="module.mjs"></script>
<script nomodule src="fallback.js"></script>

这可能是此处所写 CORS 错误的主要原因:

与常规脚本不同,模块脚本(及其导入)被获取 与 CORS。这意味着跨域模块脚本必须返回有效 CORS 标头,例如 Access-Control-Allow-Origin: *

所以你需要在模块文件中添加CORS头

请考虑 this blog 处理 CORS 问题。您应该添加 CORS 标头,即。 Access-Control-Allow-Origin: * 很可能是服务器配置。

【讨论】:

【参考方案6】:

在浏览器中使用 JS 模块 在 Web 上,您可以通过将 type 属性设置为 module 来告诉浏览器将元素视为模块。

<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>

更多 https://developers.google.com/web/fundamentals/primers/modules

【讨论】:

【参考方案7】:

如果你使用 webpack 和 babel 并且想将代码导入到你的包中,我猜它应该是以下之一:

export default function show_message()
    alert("Hello");

然后在你的代码中:

import show_message from 'path/to/show_message.js'
// or 
import  default as someOtherName  from 'path/to/show_message.js'

或者,如果您想导出多个函数:

const show_message = function()
    alert("Hello");

export  show_message ;

然后在你的代码中:

import  show_message  from 'path/to/show_message.js'
// or 
import  show_message as someOtherName  from 'path/to/show_message.js'

希望对您有所帮助。

【讨论】:

【参考方案8】:

0。简短的回答

您需要安装并运行本地 Web 服务器。 - 关于如何的建议, 继续阅读。

1。基础知识

我尝试了一个简单的 HTML 文件——index.html——如下:

<!-- index.html - minimal HTML to keep it simple -->
<html>
<head>
  <meta charset="UTF-8">
  <link rel="shortcut icon" href="#">
</head>
<body>
  <h1>Hello world!</h1>
  <p>Experimenting with JavaScript modules.</p>
  <script type="module" src="js/functions.js"></script>
</body>
</html>

在子文件夹js我把JavaScript文件functions.js:

// js/functions.js
alert('Hello');

双击index.html时,我的默认浏览器——Firefox 89.0 (64 位)- 按 F12 后显示以下内容。 注意 JavaScript 代码是如何没有运行

错误信息:Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///C:/stackexchange/reproduce/jsModule/moduleNW/basics/js/functions.js. (Reason: CORS request not http).

作弊“解决方案”是(暂时)从 HTML 中删除 type="module" 代码。 然后警报显示没有错误。

但我想要将 JavaScript 代码作为模块运行,所以我放回去了 type="module" 在 HTML 中。

2。安装并运行本地 Web 服务器

要将其作为模块运行,它需要在 Web 服务器上运行。 因此,如果您想在自己的计算机上运行代码,则需要 (安装和)启动本地网络服务器。 目前流行的一种替代方法是 live-server。 这对我有用。

打开一个终端。 (在 Windows 上:cmd.exe。) 输入npm并按Enter查看是否安装了Node.js。 如果你得到command not found,请在https://nodejs.org/en/download/下载 并安装。 1 (在 Ubuntu 上,你可以试试sudo apt install -y nodejs。) 安装实时服务器:npm install live-server -g。 将目录更改为您的页面所在的位置:cd &lt;path-to-index.html&gt;。 启动服务器:live-server . (应该在默认浏览器中打开 localhost:8080 并显示警报。 见下文。)

注 1。 我在 Windows 10 上,但上述说明在 Linux 和 macOS 也是。注 2。 这里我使用的是 Firefox 89.0,但我也尝试过 Google Chrome 91.0。 唯一显着的区别是 CORS 错误消息,在 Chrome 中显示为:Access to script at 'file:///C:/stackexchange/reproduce/jsModule/basics/js/functions.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.

3。导出和导入

接下来我创建一个新文件夹demo2,其中包含以下demo2.html

<!-- demo2.html - even shorter HTML for simplicity -->
<body>
  <h1>Hello world!</h1>
  <p>Javascript modules.</p>
  <script type="module" src="js/main.js"></script>
</body>

我还在子文件夹js中创建了以下三个JavaScript文件:

// js/module1.js
export function hi ()  console.log('Hi from module 1.'); 

// js/module2.js
export function howdy ()  console.log('Howdy from module 2!'); 

// js/main.js
import  hi  from './module1.js';
import  howdy  from './module2.js';
hi();
howdy();

现在我从终端在 demo2.html 所在的文件夹中运行 live-server 居住。 这次我开始输入 live-server --port=1234 --entry-file=demo2.html 并点击 Enter。截图:

参考资料:

Installing Node.js live-server The live-server docs Live-server can't find the file specified Export and Import

1 在 Windows 10 上,我曾经需要 repair the installation.

【讨论】:

我得到“live-server : FIle c:\path\to\live-server.ps1 无法加载,因为在此系统上禁用了运行脚本。” :( 无法加载,因为在这个系统上禁用了运行脚本 ~ * ~ 我用的是老式的cmd.exe,所以在PowerShell中不知道怎么做.如果你坚持使用 PowerShell,不妨看看How to enable execution of PowerShell scripts? - or - PowerShell says “execution of scripts is disabled on this system.” 是否有帮助? 对不起,我来晚了,但您可以在 PowerShell 中运行 Set-ExecutionPolicy AllSignedSet-ExecutionPolicy Bypass -Scope Process【参考方案9】:

我知道这个旧线程,但我只是通过使用 Parcel 启动我的网站 Parcel index.html 自己解决了这个问题,在我的情况下,我使用的是 Live 服务器,直到我切换到 parcel 才工作。

【讨论】:

【参考方案10】:

Accepted answer 的快捷方式

如果您使用的是Visual Studio Code,只需通过Microsoft 安装Live Preview 扩展。

在任何 HTML 文件中单击 显示预览 图标。它将自动运行本地服务器并显示在代码编辑器中。每次编辑后,您都会刷新。您也可以在默认浏览器中显示它。

不再需要命令行!

【讨论】:

【参考方案11】:

不要使用.js,而是尝试使用.mjs。 假设您的模块文件是/modules/App.js,只需将其更改为/modules/App.mjs。 当然,请确保您在脚本标签中添加了 type="module",如下所示 - &lt;script type="module" src="./index.js" defer&gt;&lt;/script&gt;

我的文件夹结构 -

index.html
index.js
modules/App.mjs

这对我有用!

【讨论】:

以上是关于Javascript模块在浏览器中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 重定向在 Facebook 应用内浏览器中不起作用

Javascript autotab keyup/keydown 在 Cordova Android 浏览器中不起作用

使用javascript禁用键盘快捷键在Safari中不起作用?

javascript代码在chrome移动浏览器中不起作用,但在桌面上它工作正常

@font-face 在 Firefox 中不起作用 [重复]

地理定位在谷歌浏览器中不起作用