【问题标题】:Javascript module not working in browser?Javascript模块在浏览器中不起作用?
【发布时间】: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 代码中?

感谢任何帮助。

【问题讨论】:

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

标签: javascript module cors cross-domain


【解决方案1】:
function show_message(){
    alert("Hello");
}

export { show_message };

import { show_message } from './functions'

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

【讨论】:

    【解决方案2】:

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

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

    更多陷阱和解决方案herehere

    【讨论】:

      【解决方案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。截图:

                参考资料:


                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
                    

                    这对我有用!

                    【讨论】:

                      猜你喜欢
                      • 2020-08-30
                      • 2011-03-06
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-10-28
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多