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

时间:2018-09-02 18:11:28

标签: javascript module

好的,我浏览了这个网站,发现了几个不同的答案,但没有一个对我有用。 基本上有一个js文件,其中包含许多功能以及该应用程序的主要代码。我想将所有功能移到另一个js文件中,以便可以稍微整理一下代码。我对js还是很陌生,但是我知道在python中它就像说“从(路径)导入(模块)为(昵称)”一样简单

无论如何,假设我的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代码中?

感谢您的帮助。

10 个答案:

答案 0 :(得分:4)

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

  

type =“ module”

如下所示:

Row cols_as_array           cols_as_string   
1   region_code             region_code,division_code,state_fips_code,state_gnis_code,state_geo_id,state_abbreviation,state_name,legal_area_code,feature_class_code,functional_status_code,area_land_meters,area_water_meters,internal_point_lat,internal_point_lon,state_geom   
    division_code        
    state_fips_code      
    state_gnis_code      
    state_geo_id         
    state_abbreviation       
    state_name       
    legal_area_code      
    feature_class_code       
    functional_status_code       
    area_land_meters         
    area_water_meters        
    internal_point_lat       
    internal_point_lon       
    state_geom    

<script type="module> import {addTextToBody} from './utils.mjs'; addTextToBody('Modules are pretty cool.'); </script>

utils.mjs

这是如果您没有使用webpack之类的捆绑软件,而是直接在浏览器中工作。

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

答案 1 :(得分:3)

1。基础知识

我尝试了一些简单的HTML代码,如下所示:

<!-- demo.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>

JavaScript代码仅一行-不计算注释:

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

我的网络浏览器显示以下内容。请注意JavaScript代码如何未运行

JavaScript not working in browser.

对于此类问题,建议采取的措施是打开浏览器的 开发工具,通常是按键盘上的 F12 。 这是Firefox 77所说的:

Firefox CORS error message.

在文本中:Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///C:/stackexchange/reproduce/jsModule/RobotMan/basics/js/functions.js. (Reason: CORS request not http).

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


但是我将JavaScript作为模块运行,所以我退回了type="module" 进入HTML文件。

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

  • 打开一个终端。 (在Windows上:cmd。)
  • 键入npm,然后按 Enter 来查看是否已安装Node.js。
  • 如果您获得command not found,请从https://nodejs.org/en/download/下载 并安装。
  • 安装实时服务器:npm install -g live-server(按用户安装)。
  • 将目录更改为页面所在的位置:cd <path-to-demo.html>
  • 启动服务器:live-server demo.html
    (应在默认浏览器中打开localhost:8080并显示警报。请参见下文。)

JavaScript running locally on live-server.

注释1 : 我在Windows 10上,但是上述说明也可以在Linux和macOS上正常工作。
注释2 : 我使用的是Firefox 77.0以上版本,但我也尝试使用Google Chrome 83.0。唯一值得注意的 区别在于,CORS错误消息在Chrome中显示为: Access to script at 'file:///C:/stackexchange/reproduce/jsModule/RobotMan/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, https.

2。导出和导入

创建一个包含以下modules的新文件夹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 --port=1234 --entry-file=demo2.html开始 并点击 Enter 。希望看到类似的东西:

JavaScript running when called from several sub-modules.

参考文献:
https://gist.github.com/donmccurdy/20fb112949324c92c5e8
https://javascript.info/import-export
https://stackoverflow.com/questions/39578877/live-server-cant-find-the-file-specified#43717740

答案 2 :(得分:2)

考虑通过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: *最有可能进入服务器配置。

答案 3 :(得分:1)

function show_message(){
    alert("Hello");
}

export { show_message };

import { show_message } from './functions'

我认为这应该可以解决问题。这是一种命名的导出/导入技术。您可以根据需要在此名称下查找更多信息。

答案 4 :(得分:1)

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

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

还有更多herehere的陷阱和解决方案。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

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

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

答案 7 :(得分:1)

如果您使用的是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)

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

>

答案 9 :(得分:0)

Accepted answer 的快捷方式

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

Live Preview in Visual Studio Code

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

不再需要命令行了!