Loading static project without webpack or CDNs - javascript

I would like to statically serve a project, that uses webcomponents (using lit-html), without any packaging tools like webpack etc.
The example project is composed of this structure:
index.html
app.js
package.json
package.json:
{
"name": "lit",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#webcomponents/webcomponentsjs": "^2.2.7",
"lit-element": "^2.0.1"
}
}
app.js:
import { LitElement, html } from 'lit-element';
class FooElement extends LitElement {
render() {
return html`<div>hello world!</div>`;
}
}
window.customElements.define('x-foo', FooElement);
and finally, index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="app.js" type="module"></script>
</head>
<body>
<x-foo></x-foo>
</body>
</html>
I serve this using a static http server and, of course, this doesn't work. The browser raises the error: Error resolving module specifier: lit-element.
So we try altering the import directive to:
import { LitElement, html } from './node_modules/lit-element/lit-element.js';
The browser then fails with: Error resolving module specifier: lit-html in lit-element.ts:14:29
I've tried using systemjs version 3.0.1 with the following modified index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<script type="systemjs-importmap" src="systemjs.map.json"></script>
<script src="./node_modules/systemjs/dist/system.min.js"></script>
<script>
System.import('app');
</script>
<x-foo></x-foo>
</body>
</html>
and a systemjs.map.json file:
{
"imports": {
"app": "./app.js",
"lit-element": "./node_modules/lit-element/lit-element.js",
"lit-html": "./node_modules/lit-html/lit-html.js"
}
}
When loading this (again via a static webserver), we get in Firefox:
import declarations may only appear at top level of a module at app.js:1.
In Chrome:
Uncaught SyntaxError: Unexpected token { at app.js:1
In Safari:
Unexpected token '{'. import call expects exactly one argument. at app.js:1
All of which suggests that systemjs isn't treating app.js as a module.
Is there anyway that we can achieve static loading of modules that have a dependency tree within node_modules?
I've pushed the version of the code with systemjs to https://github.com/dazraf/lit-test.
Thanks.

You can perhaps use something like this in your app.js
import {LitElement, html} from 'https://unpkg.com/#polymer/lit-element/lit-element.js?module';
And this in your HTML code
<script type="module" src="./app.js">
It worked for me. If you don't want to use unpkg you can download it and serve it locally.

We have a server that does just this, and only this: https://open-wc.org/developing/owc-dev-server.html
It's simple server that does the minimal amount of work required and is specifically designed to work with the native es module loader available in all major browsers.
In the future, this should no longer be necessary when import maps are standardized.

Allow me to blow your mind. Difficult to find, a coworker actually found it.
https://codewithhugo.com/use-es-modules-in-node-without-babel/webpack-using-esm/

Related

Serving SvelteKit app through VSCode Webview API

This question is being asked after spending weeks and giving up multiple times on trying to solve this.
I'm developing a VSCode extension that needs to make use of the Webview API. For a while, this could be using Svelte, but now with SvelteKit released as stable and being treated as default when you do npm create svelte, I targetted to use that. After configuring the app to be static SPA with SSR turned off and using the #sveltejs/adapter-static, it seems that serving it is not the same as it was with vanilla Svelte.
This is the svelte.config.js:
import adapter from '#sveltejs/adapter-static';
import preprocess from 'svelte-preprocess';
/**
* Consult https://github.com/sveltejs/svelte-preprocess
* for more information about preprocessors
*
* #type {import('#sveltejs/kit').Config} */
export default {
preprocess: preprocess(),
kit: {
adapter: adapter({ fallback: 'index.html' }),
// ssr: false, // deprecated
csp: {
directives: {
'default-src': ['none'],
'img-src': ['{{cspSource}} https:'],
'script-src': ['{{cspSource}}'],
'style-src': ['{{cspSource}}'],
},
},
// paths: {
// base: '{{baseURL}}', // not accepted
// },
},
};
This is the built HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width" />
<meta http-equiv="content-security-policy" content="default-src 'none'; img-src {{cspSource}} https:; script-src {{cspSource}} 'sha256-N2DRY+AREasGSTE5X4BdHoEYZsaGOpTvUwTBIHmryVA='; style-src {{cspSource}}">
<link rel="modulepreload" href="/_app/immutable/start-e16b6a0f.js">
<link rel="modulepreload" href="/_app/immutable/chunks/index-0576dc7c.js">
<link rel="modulepreload" href="/_app/immutable/chunks/singletons-51070258.js">
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">
<script type="module" data-sveltekit-hydrate="45h">
import { start } from "/_app/immutable/start-e16b6a0f.js";
start({
env: {},
paths: {"base":"","assets":""},
target: document.querySelector('[data-sveltekit-hydrate="45h"]').parentNode,
version: "1672682689612"
});
</script></div>
</body>
</html>
Contrary to vanilla Svelte that would generate something like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width" />
<script src="/dist/app/main.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
That could be served through Webview like:
function getWebviewContent(webview, context) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="${[
"default-src 'none'",
`img-src ${webview.cspSource} https:`,
`script-src ${webview.cspSource}`,
`style-src ${webview.cspSource}`,
].join(';')};"
/>
<title>My Extension</title>
<script type="module" crossorigin src="${webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'dist/app/main.js')
)}"></script>
<link rel="stylesheet" href="${webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'dist/app/style.css')
)}">
</head>
<body><div id="app"></div></body>
</html>
`;
}
The file is bit more complex now, so I can't (and shouldn't) try to rewrite it in this function.
The following are the conditions:
VSCode needs absolute paths since it has different environments and protocols. Keep in mind that an extension is served locally to every user. (context.extensionUri is IMPORTANT)
SvelteKit has its set of configurations (different from Vite) that may pose to be restrictive specially with SPA mode.
Content Security Policy for Webview is also restrictive to what and what can't be used.
Probably due to Vite, the file names have hashes, so it's not consistent - but I'm preferring to keep that.
The script block in the HTML (may also need a nonce) is importing the start function relatively as a module.
Instead of writing another template as a string for VSCode that would need to be maintained, it would be ideal to have the generated HTML read into VSCode and served. Using Mustache seems good (hence you see {{cspSource}} in the HTML above).
How would one suggest to architecture and integrate this?

Javascript importing issuse, can't import vanta.js

I had downloaded two javascript libraries throw this command
$ npm install --save vanta three
vanta.js and three.js , vanta has cool animation that makes your website look nice. I follow some tutorial and I wrote every line same as in the tutorial two of these lines are
import * as THREE from "three";
import BIRDS from "vanta/dist/vanta.birds.min";
this gives me an error:
Uncaught TypeError: Error resolving module specifier "name of the module" Relative module specifiers must start with “./”, “../” or “/”.
I was surprised how they wrote code that is not working so I google it , solution is to write the whole path like:
import * as THREE from "./node_modules/three/build/three.js";
import BIRDS from "./node_modules/vanta/dist/vanta.birds.min.js";
The THREE.js error is gone but the pain comes with vanta.js error:
Uncaught SyntaxError: ambiguous indirect export: default
I look on the internet for this I didn't find anything that helps me with this problem and I don't know why this happen, I follow every step in these tutorials but it work for them not me :_(
import * as THREE from "./node_modules/three/build/three.js";
import BIRDS from "./node_modules/vanta/dist/vanta.birds.min.js";
const root = document.getElementById("root");
BIRDS({
el: root,
THREE,
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css.css" />
<title>VANTA</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="js.js"></script>
</body>
</html>

How to export variables to other javascript file

I want to use variables which is in main.js file in other js file and I tried everything ( exporting modules, declaring global variables) but nothing works and I have to do it because other js file is greatly dependent to those variables which are in main.js file.
Is there any other way to do it, if yes, please enlighten me.
Since you've stated that you're writing JavaScript code to be executed in web browsers, here's what your main.js file may look like (holding the variable importantVariable):
const importantVariable = 10;
Next, we have another JavaScript file, other.js (using the variable importantVariable):
console.log(importantVariable);
In the HTML document, where you're willing to use the scripts, include the main.js BEFORE the other.js file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="main.js"></script>
<script src="other.js"></script>
</body>
</html>
You should get "10" in the console, which indicates that the variable sharing of one file with other[s] worked successfully.
Explanation: A variable in the global scope should be accessible to all scripts loaded after it is declared.
We can use es modules in browsers.
index.html
<!DOCTYPE html>
<html>
<body>
<script type="module" src="./main.js"
</body>
</html
main.js
import { message } from "./other.js";
console.log(message)
other.js
export const message = "haha"
Note:
Due to the CORS policy, openning index.html directly will throw an error.
...has been blocked by CORS policy...
So you need to deploy them in an server.
Have you tried importing it into the receiving JavaScript file? This can sometimes be necessary as well as exporting it. Here's an example
In index.js:
export someVariable
In otherFIle.js: import { someVariable } from './index'

createVNode is not a function (Vue with Laravel)

I'm trying to make a component render as per an example I found online.
I created a sample project and it works fine there, but it crashes when I'm trying to use the same thing on the official code base.
here is the contents of the blade file which is rendered.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue SPA Demo</title>
</head>
<body>
<div id="app">
asdfsadfsadsdf
<example-component></example-component>
</div>
<script src="js/app.js"></script>
</body>
</html>
then, here is app.js
window.Vue = require("vue").default;
import ExampleComponent from './components/ExampleComponent.vue';
Vue.component('example-component', ExampleComponent);
and here is ExampleComponent.vue
<template>
<div>
<div>Example Component</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
}
}
</script>
here is what the page looks like:
and here is the error:
Fun fact: when I try to include the component like this instead, it displays "Test" as expected
Vue.component('example-component', {
template: '<div>Test</div>'
});
so it is clear to me that this line/file is the issue
import ExampleComponent from './components/ExampleComponent.vue';
I found the answer!! After almost 8 hours...
Turns out the "vue-loader" 16.1.2 from package.json was the mistake. I tried the exact same configuration but changed "16.1.2" to "15.9.2" and vice-versa 4-5 times and running
rm -rf node_modules/
rm package-lock.json
npm cache clear --force
npm install
in-between every package change.
Fun fact: after that, your component will render when you write
const app = new Vue({
el: '#app',
});
in your app.js

How to solve 'Unhandled Promise Rejection: Error: Unable to resolve bare specifier "app.js" from http://localhost:3000/'

I have been studying typescript.
I am encountering the below error while studying node modules.
Clicking on the anonymous function take me to the below code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="author" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Learning TypeScript</title>
<script src="node_modules/systemjs/dist/system.js"></script>
</head>
<body>
<script>
System.import('app.js')
</script>
</body>
</html>
Here is the link to my demo project
If you are using newest version of SystemJS. You have to make some change:
index.html: use System.import('./app.js') instead of System.import('app.js') // hmm
tsconfig.json: use "module": "system" instead of "module": "commonjs".
app.ts: use import { PI, calculateCircumference } from "./maths/circle.js"; instead of import { PI, calculateCircumference } from "./maths/circle"; // hmm
(I can not find a way to config baseUrl or defaultExtension)
Run tsc command to rebuild app.js file before you reload html page on browser.

Categories

Resources