Uncaught SyntaxError: Cannot use import statement outside a module Vue 3 PWA Workbox - javascript

I am trying to convert my vue js app into a PWA. Following the workbox documentation in the following link:
https://developers.google.com/web/tools/workbox/modules/workbox-strategies
I have to import some modules
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
import { Queue } from 'workbox-background-sync';
After running npm run build, vue js automatically generates the following line of code which is at the top of service-worker.js file followed by the imports mentioned above:
importScripts("/precache-manifest.f6666fe9d8f679ee90db8a98ef900aa4.js", "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
My app is fully functional without any errors, if I remove the imports, the service worker is registered successfully. When i add the imports I am getting this error:
Uncaught SyntaxError: Cannot use import statement outside a module
Error during service worker registration: TypeError: Failed to register a ServiceWorker for scope ('http://127.0.0.1:8887/') with script ('http://127.0.0.1:8887/service-worker.js'): ServiceWorker script evaluation failed
From my research I have learned that the scripts need to be bundled using webpack or a similar service.
https://developers.google.com/web/tools/workbox/guides/using-bundlers
However since I am using the CDN to importScripts, according to my understanding it should automatically bundle as stated in the following website:
https://developers.google.com/web/tools/workbox/modules/workbox-sw

It's an either-or thing: if you have full control over your build a bundling process, then following the "Using bundlers with Workbox" guide and using the ES module import {...} from '...' syntax, but not using workbox-sw, would work.
If you don't have full control over your build process (and it sounds like you don't), then you can use workbox-sw to load the rest of Workbox. Since you already have the importScripts('/path/to/workbox-sw.js') in your service worker, using statements like workbox.routing.registerRoute() or workbox.strategies.registerRoute() in your service worker, and not putting in any import {...} from '...' statements, should just work.

Related

Laravel 9 - using vite to do a js import within a blade template

I am trying out Laravel 9 with Vite, but without(!) a frontend framework (like Vue or React).
I am trying to make a reusable js module that I could use/load in different Blade templates.
So I created a file 'menu-btn-toggle.js' in 'resources/js/components/utilities'.
export class MenuBtnToggle
{
constructor() {
console.log('MenuBtnToggle');
}
}
I then created a 'utilities.js' file in 'resources/js/components'.
import './utilities/menu-btn-toggle';
I then updated the 'app.js' file in 'resources/js'
import './bootstrap';
import './components/utilities';
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
So far, this seems to be working (?). Atleast, i think so. Vite is not giving me any errors so far (yay!)
But then I try to import the module in a blade template, but I can't get it to work.
So at the bottom of my blade template, I added this:
<script type="module">
import MenuBtnToggle from 'menu-btn-toggle';
new MenuBtnToggle();
</script>
But this gives me the following error:
Uncaught TypeError: Error resolving module specifier “menu-btn-toggle”. Relative module specifiers must start with “./”, “../” or “/”.
But when I add one of the examples, the error changes to:
Loading module from “[local_dev_url]/menu-btn-toggle” was blocked because of a disallowed MIME type (“text/html”).
as it isn't be able to find the module. It returns a 404.
Is it even possible do to want I want without a frontend framework? Or am I not seeing something obvious? I have experience with php, unfortunately not (enough) with Laravel and Vite.
I was stuck into almost same situation where we are not able to use import statement inside our blade files using Vite. We commonly get
Uncaught TypeError: Error resolving module specifier
“menu-btn-toggle”. Relative module specifiers must start with “./”,
“../” or “/”.
or We get 404 Blocked error nearly same as
Loading module from “[local_dev_url]/menu-btn-toggle” was blocked
because of a disallowed MIME type (“text/html”).
When importing external npm packages or modules, we need to put them in windows object just like you did above for Alpine
window.Alpine = Alpine;
But for your specific case problem you must do following
1)Inside menu-btn-toggle.js
export class MenuBtnToggle
{
constructor() {
console.log('MenuBtnToggle');
}
}
2)Inside utilities.js
import {MenuBtnToggle} from "./utilities/menu-btn-toggle";
window.MenuBtnToggle = MenuBtnToggle;
And then finally inside your app.js
import './components/utilities';
Now inside your .blade file, there is no need to import the MenuBtnToggle
instead just do it like
new MenuBtnToggle();
No need to use import MenuBtnToggle from 'menu-btn-toggle'; in blade.
Important thing is to import your app.js file properly inside .blade file through vite
#vite(['resources/css/app.css','resources/js/app.js'])
And it works. It has worked when reproducing same files/setup as yours.

How can I avoid app crashing because of importing jest?

I tried many ways of importing jest into my project. All of them cause my app to crash displaying the blank screen when visiting localhost:3000 even though all statements cause app to compile (the single line of import causes the app to crash):
import { mocked } from "ts-jest"
import { mocked } from '#jest/globals'
import { jest } from 'ts-jest'
import { jest } from '#jest/globals'
App crashes with the following error:
VM551:2 Uncaught ReferenceError: process is not defined
I have the following dependency in package.json:
"ts-jest": "^28.0.7"
What might be the reason behind crashing? What is the correct way to import jest? I need specifically mocked object to be available, is there a right way to make it work without crashing the app?
It sounds like you're trying to import jest or mocked into your application code that runs in the browser, which won't work. process is a global in Node, but not in the browser, which is why you're getting this error:
Uncaught ReferenceError: process is not defined
If you're trying to use mock data, you can define that data in a separate file that you can import both in your test files (which run in Node) and in your application code (which runs in the browser).

Cannot import a node module inside a module web worker on the browser

1- I am trying to import a node module into my worker. I could not find a way to get it done in a straightforward manner. Many people were suggesting using things like webpack or external libraries. Why can't I simply import the node module like a regular js module import like so?
import blazeface from '#tensorflow-models/blazeface';
meanwhile, I can import other modules I created like
import getDetectedFace from "./detectFace.js";
When this error occurs I do not see any output to the console that an error has occurred. I can only tell because my worker does nothing when I try this type of import. Is this normal?

ES module imports - can it always be done? A failed example trying to import socket.io-client

I'm trying to use a "build-less" process so I'm using a plain module script in an html file (following the Preact docs):
<script type="module">
import {
html,
render,
} from 'https://unpkg.com/htm/preact/index.mjs?module';
function App(props) {
return html`<h1>Hello ${props.name}!</h1>`;
}
render(html`<${App} name="world" />`, document.getElementById('root'));
</script>
I'm able to get the client socket.io working if I by-pass the module system and rely on the window global (note: I'm serving the html file from an http server that's been passed to socket.io's server and have /socket.io/socket.io.js automatically installed):
<script src="/socket.io/socket.io.js"></script>
<!-- in previous module script: -->
const socket = window.io();
socket.on('connect', () => {
console.log('socket id>>', socket.id);
});
I would like to import the socket.io client from an ES module. I know I could encapsulate the window use in my own JS file and then import that in the module script in my html, but I'm trying to do this instead and it isn't working:
import io from '/socket.io.js'; // after copying socket.io.js to my public dir
import { io } from 'https://cdnjs.cloudflare.com/ajax/libs/engine.io-client/3.5.0/engine.io.js'; // I have tried several variations of urls and what is imported
Judging by:
Uncaught SyntaxError: The requested module '/socket.io.js' does not
provide an export named 'default'
and by the "polyfill"ed (if that's the correct term) commonjs globals like module in the probably-webpack bundle which is socket.io.js - it is likely that there just is no support for ES modules for this library.
I will probably be facing this issue over and over so I have decided to go back to having a build step.
My question is - is there a way around this "3rd party libraries not supporting ES module imports out of the box"? Maybe with a little work on my part I can get around this and try completing a small project without a build step in development.
Is there a way around this "3rd party libraries not supporting ES module imports out of the box"?
Unfortunately no, at least not always. It is impossible for a browser to natively import something that is not an ES module. However, if you've got access to the original source code, and the source code itself is written as an ES module (and then transpiled/bundled), you can sometimes build ES modules out of it yourself.
In the case of socket.io, their repo hosts the source code in TypeScript, which makes use of import/export. Unfortunately, their code also makes use of require() and other npm packages, which ultimately means it cannot be trivially converted to an ES module.

Using Vue Design System in Nuxt is throwing errors about export in system.js

I am trying to get the components imported into a Nuxt project, following the steps here:
https://github.com/viljamis/vue-design-system/wiki/getting-started#using-design-system-as-an-npm-module
Nuxt does not have a main.js (everything is plugin based), so what I have done is create a "plugin" and then do the import code in there like so (Nuxt recommends this for other libraries too and works fine):
vue-design-system.js
import Vue from 'vue'
import system from 'fp-design-system'
import 'fp-design-system/dist/system/system.css'
Vue.use(system)
Then in my config I do (removed other code in config):
nuxt.config.js
module.exports = {
css: [
{ src: 'fp-design-system/dist/system/system.css', lang: 'css' }
],
plugins: [
{ src: '~plugins/vue-design-system', ssr: true }
]
}
When I run npm run dev in my theme, it builds, but I get a warning:
WARNING Compiled with 1 warnings warning in
./plugins/vue-design-system.js 7:8-14 "export 'default' (imported as
'system') was not found in 'fp-design-system'
Seems to have an issue with the generated system.js regarding the export (the command npm run build:system).
In my page on screen I get the following error when trying to use a component in the design system:
NuxtServerError Cannot find module
'fp-design-system/src/elements/TextStyle' from
'/Users/paranoidandroid/Documents/websites/Nuxt-SSR'
If I hard refresh the page, I then get another message:
NuxtServerError render function or template not defined in component:
anonymous
Any idea what's happening here? It would be really great to get this working somehow.
At this current time, I'm not sure if it's a Nuxt issue or a Vue Design System issue. I think the latter, just because the Nuxt setup I have right now is very bare-bones...so it's not something else causing this.
Thanks.
Repository on GitHub:
Here is the repo for my "theme", but in order to get this going, you will need to create a design system separate from this with the same name and follow the steps to use the design system as a local (file) NPM module.
https://github.com/michaelpumo/Nuxt-SSR
console.log of system (from the JS import statement)
As for your first error (""export 'default' (imported as 'system') was not found in 'fp-design-system'"), the UMD built JS from vue-design-system does not export a "default" object. But you can simply workaround the issue by importing it as:
import * as system from 'fp-design-system'
instead of:
import system from 'fp-design-system'
Then another issue comes quickly as you noticed in your comments: "window is not defined", due again to the UMD built JS that expects window to be globally available, instead of the usual trick to use this (which equals window in a browser). Therefore as it is, the build is not comptible with SSR.
You could however slightly rework the built JS by replacing the first occurrence of window by this, but I am not sure if the result will still work.
Most probably you should better keep this module for client rendering only.
It seems Vue is looking for the ES6 pattern for importing module, which you should use for external javascript modules/files.
in ES6 it is
export default myModule
in ES5 it was
module.exports = myModule
Hope it will help.

Categories

Resources