Let me start out by saying that I have very little experience with HTML, javascript and overall website creation and hosting, so sorry in advance if the information I am providing is lacking.
I am trying to make a website by using a 3d object from three.js, however, nothing is loading in the 'live server' (when I upload the entire website to Cpanel), however, when I use visual studio code to run it through my local server (through the command npm run dev) the website is showing as intended. I have screenshotted the pages:
correct page
incorrect page
When I open the element inspect on the broken page, I get the following error through the console:
Failed to load module script: Expected a JavaScript module script but the server responded with a
MIME type of "text/css". Strict MIME type checking is enforced for
module scripts per HTML spec.
and
Uncaught SyntaxError: Cannot use import statement outside a module
i have the following code in my script.js:
import './style.css'
import * as THREE from '../node_modules/three/build/three.module.js'
import { OrbitControls } from '../node_modules/three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from '../node_modules/three/examples/jsm/loaders/GLTFLoader.js'
import { HemisphereLight, Sphere, SRGB8_ALPHA8_ASTC_12x12_Format, sRGBEncoding, Texture, TextureEncoding } from '../node_modules/three/build/three.module.js'
import gsap from '../node_modules/gsap/all.js'
var gltfLoader = new GLTFLoader()
let tl = gsap.timeline()
var diamond = null
I am also using this to call the script in the index.html, however, I am uncertain if this is the correct way of calling the script.
<script type=module src="script.js"></script>
How would I be able to fix this? any help would be appreciated!
No.
Understand that the browser import functionality is very different than that of Node, or development with a bundler like Webpack. In browser imports, scripts have to be of type module (thus causing the cannot use import statement out of module error) <script type="module" ... (with the quotes!). You also need to reference an import file starting with ./, ../, or / (which you already are doing). Finally, you may only import JavaScript files, not CSS.
You have two options:
Use a bundler like Webpack to compile your files into a single one (and remove the import statements)
(preferred) Remove import './style.css' and add <link rel="stylesheet" href="./style.css" type="text/css" /> in your HTML <head>
Related
I am trying to install the Popup picker from Picmojs but I am limited by the following:
I can't modify any file as I am integrating the code in a co-code builder (no access to index.js,..) but can host files
I can't use NPM nor Yarn as I am working in the browser
Here's what the documentation says
Use ESM from CDN You can also import the ESM version of PicMo
directly. You will first to create an ES module that imports PicMo:
index.js import { createPicker } from 'https://unpkg.com/picmo#latest/dist/index.js';
createPicker(...);
Then you can import the local module from a script tag:
<script type="module" src="index.js"></script>
I indeed tried in a Fiddle (even without the script that as I didn't understand this part) and it seems to be working all fine: Link to Fiddle
However, this relates to the createPicker function, but I'm interested in the Popup picker and therefore need the createPopup function.
According to their documentation:
A popup picker is not displayed until it is triggered by clicking on a
popup trigger, usually a button.
To use a popup picker, you must first install the #picmo/popup-picker
package. This package contains the createPopup function.
createPopup(pickerOptions: PickerOptions, popupOptions: PopupOptions):PopupPickerController
-> I don't know how to "first install the #picmo/popup-picker package".
Here's what I tried based on the previous working example:
import { createPopup } from 'https://unpkg.com/#picmo/popup-picker#latest/dist/umd/picmo-popup.js';
Link to Fiddle
But I always get the same error: "<a class='gotoLine' href='#43:10'>43:10</a> Uncaught SyntaxError: The requested module 'https://unpkg.com/#picmo/popup-picker#latest/dist/umd/picmo-popup.js' does not provide an export named 'createPopup'"
Any hint for me? I'm really stuck on this part.
You're trying to use the UMD version of the library, but you can't use UMD with ESM.
Based on your URL, I tried https://unpkg.com/#picmo/popup-picker#5.4.0/dist/index.js which gave me this error:
TypeError: Failed to resolve module specifier "picmo". Relative references must start with either "/", "./", or "../".
That tells us that the file uses import ____ from "picmo", which won't work in the browser without an import map. If your target browsers support them, we can do that like this:
<script type="importmap">
{
"imports": {
"picmo": "https://unpkg.com/picmo#5.4.2/dist/index.js",
"#picmo/popup-picker": "https://unpkg.com/#picmo/popup-picker#5.4.0/dist/index.js"
}
}
</script>
<script type="module">
import { createPopup } from "#picmo/popup-picker";
console.log(typeof createPopup);
</script>
...but sadly as I write this import maps are just supported by Chromium-based browsers like Chrome, Edge, and Opera, not Firefox or Safari.
If you need to target those as well, the import ____ from "picmo" would seem like an insurmountable barrier, but unpkg.com has a feature to "expand" bare imports. From the unpkg home page:
Query Parameters
?meta
Return metadata about any file in a package as JSON (e.g. /any/file?meta)
?module
Expands all “bare” import specifiers in JavaScript modules to unpkg URLs. This feature is very experimental
And indeed, adding ?module to that URL to ask unpkg to do that for us works:
<script type="module">
import { createPopup } from "https://unpkg.com/#picmo/popup-picker#5.4.0/dist/index.js?module";
console.log(typeof createPopup);
</script>
Since that imports picmo, you'll want to watch the network tab to see what exact URL is used to import picmo and use that if you need to import it in your code (so you're getting the same instance). For instance, when I did that just now it requested https://unpkg.com/picmo#%5E5.0.1?module and got a redirect pointing to https://unpkg.com/picmo#5.4.2?module which also returned a redirect pointing to https://unpkg.com/picmo#5.4.2/dist/index.js?module. That would suggest you want to import picmo from https://unpkg.com/picmo#%5E5.0.1?module (the first URL, since that's what the JavaScript engine will have seen), but you'll need to experiment to be sure.
All of that aside, it's well worth dropping them a note asking whether this is really how you should do it and/or asking for a way that doesn't rely on a "very experimental" feature of unpkg.com.
(Source #joeattardi from Github)
You're using the UMD version of the module with an import statement. This won't work; only ES modules work with imports. UMD modules are loaded with a script tag.
But then you are mixing an ESM import (your import of the main picmo package) with a UMD, which won't work either.
Two options:
Use the UMD version of the base picmo package as well, both loaded with script tags.
Use the ESM distribution of #picmo/popup-picker from unpkg. Note that you will need to add ?module to the URL, otherwise your browser will likely give an error about an invalid relative path. If you do it this way you don't need the picmo import since the popup module imports it.
So for the ESM route, you need just a single import:
import { createPopup } from 'https://unpkg.com/#picmo/popup-picker#latest/dist/index.js?module';
Diving into the specifics, I am trying to import code from a JS file called GLTFLoader for Three.js. The goal is to parse a .GLB file and render a Teapot.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Three.js #1
</title>
<style>
body{margin: 0;}
</style>
</head>
<body>
<script src="js/three.js"></script> // A dependecy.
<script src="js/cube.js"></script> // The main script.
<script src="js/loaders/GLTFLoader.mjs"></script> // The module I am trying to import code
</body> // from.
</html>
The Import code and code requiring the import. Can upload full code if need be.
import {GTLFLoader} from "js/loaders/GLTFLoader.mjs"
// Create a mesh.
const loader = new GLTFLoader(); // Instantiate loader.
loader.load("assets/models/utahteapot.glb", function (gltf) { // Load the model.
scene.add(gltf.scene); // Add the loaded model to scene.
}, undefined, function (error) { // Return an error if there is one.
console.error(error);
});
I have tried using the "type="module"" tag within the script tag, I have tried uploading the Loader code straight from the url source, I have tried importing the code within the HTML file, and I even tried creating a local server to host these files. I wasn't doing that before, and I still am now. I have ran out of ideas; I can't find a solution.
EDIT: Forgot to mention, the file GLTFLoader extension is .MJS because of an unrelated error I had along this error.
I found a solution. It wasn't how I typed or indexed the files, it was how I was serving them on my local server.
The MIME error was caused by the files always returning as an improper MIME type "plain/text" when I needed it to return as "application/x-javascript".
The import error was caused by me not adding type="module" to my main.js file within the HTML file.
So, I scouted for a python script that created a LocalHost server that served the files properly. So that meant I can label the main.js file as a module, and import what I needed from other files.
Here is the script's git.
NOTE: You may have to change your localhost number. The set number is 8080, and I had to change mine to 8090 before my files actually updated. Keep that in mind if your files aren't updating or an error is returned.
Description
I am trying to use the OrbitControls from THREE.js in my project. When I attempt to import the OrbitControls object, I am getting the following error message in the Google Chrome DevTools console.
The requested module './three.js' does not provide an export named 'EventDispatcher'
When I manually inspect three.js (r119), I can see that it does export EventDispatcher on line 50631.
Question: Given this information, why am I getting the aforementioned error message, and how can I fix this?
HTML
<!DOCTYPE html>
<html lang="en">
<body>
<script src="three.js" crossorigin="anonymous"></script>
<script src="main.js" type="module"></script>
</body>
</html>
main.js
import { OrbitControls } from './OrbitControls.js'
EDIT: Thanks to Steve, the root cause of my issue was that I was using the non-module version of three.js instead of the correct one (for my use case) called three.module.js. If you're getting the error message, make sure you're downloading the three.module.js file.
I'm assuming you're using the OrbitControls.js found in https://github.com/mrdoob/three.js/blob/dev/examples/jsm/controls/OrbitControls.js
You're mixing the module library with the non-module library. If you look at the first lines of OrbitControls.js
import {
EventDispatcher,
MOUSE,
Quaternion,
Spherical,
TOUCH,
Vector2,
Vector3
} from "../../../build/three.module.js";
It's trying to import variables from ../../../build/three.module.js, which probably doesn't exist. From your error message, it seems like someone already edited it to be './three.js', which sounds like the non-module version.
Solutions
Preserving references
Download all of three.js to a folder (like lib/three)
(Optionally) Delete files you don't need
Import via:
import { OrbitControls } from './lib/three/examples/jsm/controls/OrbitControls.js';
import * as THREE from './lib/three/build/three.module.js';
Modifying only the files you need
Or you can download only the files you need and change the references:
Download three.module.js from https://github.com/mrdoob/three.js/blob/dev/build/three.module.js
Replace ../../../build/three.module.js in OrbitControls.js to the appropriate path. It should be where three.module.js is in relationship to OrbitControls.js
Delete the <script src="three.js"> tag in your HTML, since OrbitControls.js directly imports it
Linking to a CDN
Alternatively, you can link directly to a CDN, like:
import { OrbitControls } from 'https://unpkg.com/three#0.119.1/examples/jsm/controls/OrbitControls.js';
import * as THREE from 'https://unpkg.com/three#0.119.1/build/three.module.js';
This works because all of the required files are hosted by the CDN
I was out of the loop when JavaScript got all fancy - I'm used to a <script src="https://somecdn/stuff.js"></script>, unsure about the package.json file, and have almost no experience with module packaging.
Sometimes I can move from a <script src="..." to import {functions} from 'https://somecdn/stuff.mjs'; without an issue. But other times it doesn't work.
Can everything be loaded through the new import statement, or are some scripts so module-unfriendly that I shouldn't bother?
To make it easier
I'm only on latest Chrome
My main script has the module tag: <script type="module" src="js/main.js"></script>
Successfully moved from script tag to import:
import {clear, del, get, keys, set} from 'https://cdn.jsdelivr.net/npm/idb-keyval#3/dist/idb-keyval.mjs';
But when I try to migrate
<script src="https://cdnjs.cloudflare.com/ajax/libs/dexie/3.0.0-alpha.6/dexie.js"></script>
it throws
Uncaught SyntaxError: The requested module 'https://cdnjs.cloudflare.com/ajax/libs/dexie/3.0.0-alpha.6/dexie.js' does not provide an export named 'default'
I'm assuming the "mjs" isn't the issue, as long as everything is being served as the right JS mimetype.
You can only import things from files that export them.
https://cdnjs.cloudflare.com/ajax/libs/dexie/3.0.0-alpha.6/dexie.js seems to only be exporting anything (by assigning to module.exports) when running in an environment where module is defined (i.e. Node).
When run in the browser, it just adds Dexie to the global object, without exporting anything.
I apologize for the simple question, but I'm pretty new to web development and JavaScript.
I want to import a package I've installed using npm, specifically shopify-buy following the guide here: https://shopify.github.io/js-buy-sdk/
The package is in my node_modules folder and I'm trying to import it into a JavaScript document using import Client from 'shopify-buy';
When I try to load everything up in Chrome, I get an error on the import line
Uncaught SyntaxError: Unexpected identifier
The Firefox error is a bit different: import declarations may only appear at top level
What am I doing wrong?
Edit:
The import line is the first line in my JavaScript file. And my HTML file is properly linked to the JS file (I think).
shopify.js
// Functions for SHOPIFY
import Client from 'shopify-buy';
const client = Client.buildClient({
domain: 'xxxxx.myshopify.com',
storefrontAccessToken: 'xxxxx'
});
index.html
<script src="javascript/shopify.js"></script>
If you want to use npm modules via the syntax, like import sth from "something" for browsers, you'd need to set up a module bundler and ES6 compiler, such as Webpack and Babel. You'd need to google them and find tutorials for setting up them accordingly.
An easy way to use the SDK seems to be using the CDN, since it's already been built for browsers to understand. Something like:
index.html
<script src="http://sdks.shopifycdn.com/js-buy-sdk/v1/latest/index.umd.min.js"></script>
<script src="javascript/shopify.js"></script>
shopify.js
const client = ShopifyBuy.buildClient({
domain: 'your-shop-name.myshopify.com',
storefrontAccessToken: 'your-storefront-access-token'
});
console.log(client);
JavaScript Modules can only be run in module-mode scripts. Change your HTML to the following:
<script type="module" src="javascript/shopify.js"></script>