single-spa set Vue as an external: defineComponent is not a function - vue.js

I am using Vue with single-spa and I decided to try to reduce the bundle size.
To do this, first I started by trying to set Vue as an external dependency by setting it in webpack.config.js of each Micro Front-end
externals: ['single-spa', 'vue'],
and setting in the root config the following:
<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-spa#5.9.0/lib/system/single-spa.min.js",
"vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.34/vue.global.min.js"
}
}
</script>
<link rel="preload" href="https://cdn.jsdelivr.net/npm/single-spa#5.9.0/lib/system/single-spa.min.js" as="script"
crossOrigin="anonymous">
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.34/vue.global.min.js" as="script"
crossOrigin="anonymous">
but when I try to load, it crashes with the following:
Uncaught TypeError: application '#workspace/foo' died in status LOADING_SOURCE_CODE: (0 , t.defineComponent) is not a function
at vue-router.esm-bundler.js:2123:38
at main.ts:32:38
at Object.execute (main.ts:32:38)
at doExec (system.js:469:34)
at postOrderExec (system.js:465:12)
at system.js:422:14
and also for another
Uncaught TypeError: application '#workspace/bar' died in status LOADING_SOURCE_CODE: (0 , o.ref) is not a function
at Object.9828 (quasar.esm.prod.jss:6:510)
at s (bootstrapp:19:32)
at 1.jss:3:16
at main.tss:54:28
at Object.execute (main.tss:54:28)
at doExec (system.js:469:34)
at postOrderExec (system.js:465:12)
at system.js:422:14

You are using a vue3 Version in your externals and Vue3's API is different from vue2.
I guess you are using quasar and vue-router in a version built for vue2, or your full Application might be built on vue2, so the different APIs will clash.
If you have Vue2 and Vue3 Microfrontends you can define two externals:
"vue": "https://vue2location.example",
"vue3": "https://vue3location.example"
And in your vue.config.js you can use named externals like this to rename from vue3 to vue:
config.externals({
vue: 'vue3'
})
(in theory you could use any naming you want)

I really don't know why, but using exactly this made it work
<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-spa#5.9.0/lib/system/single-spa.min.js",
"vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.29/vue.global.prod.min.js",
"vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.12/vue-router.global.prod.min.js",
"vue-i18n": "https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/9.2.0-beta.35/vue-i18n.global.prod.min.js"
}
}
</script>
<link rel="preload" href="https://cdn.jsdelivr.net/npm/single-spa#5.9.0/lib/system/single-spa.min.js" as="script"
crossOrigin="anonymous">
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.29/vue.global.prod.min.js" as="script"
crossOrigin="anonymous">

Related

Vue compiler can't resolve 'vue'

Version
3.0.5
Reproduction link
https://github.com/clark-cui/vue3-problem
Steps to reproduce
yarn
npm run dev
What is expected?
devServer work successfully.
What is actually happening?
Module not found: Error: Can't resolve 'vue' in 'F:\workspace_github\vue3-problem'
I didn't use vue-cli or vite to build this reposity.
so I use "vue-loader": "^16.1.2" and "#vue/compiler-sfc": "^3.0.0" to resolve '.vue'.
If i use cdn to import vue.Then it occur error like this.
If i use npm to import vue.This problem is solved.
This hadn't happen in vue2.I guess it's vue-compiler 's falut.
I want to use vue with cdn.How to solve this?
In order to work with vue from CDN you have to configure externals to tell webpack uses the external one. Additionally you have to refine a few things as following to make it work properly:
// webpack.config.js
module.exports = {
// ...
externals: {
// tell `webpack` to resolve `vue` from root (window)
vue: "Vue",
},
devServer: {
// ...
// might have to turn of this option since it throws error
// not sure where it comes from though :(
hot: false,
}
}
Refine the template a bit:
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Move the script to here to ensure load `Vue` before your script -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.0/vue.global.prod.js"></script>
<title>Vue demo</title>
</head>
<body>
<noscript>
<strong>error</strong>
</noscript>
<div id="app"></div>
</body>
</html>

Can I make this workflow faster? Rollup watch / npm live-server

I'm trying to achieve a 'live' workflow for a website i'm about to build.
It's based on this boilerplate.
I currently have this workflow working:
Write code -> Save -> 'Rollup watch' rebuilds build/main.js from src/main.js -> 'live-server' refreshes browser.
I'm new to a lot of this, so i'll be honest and say that the 8s it takes per build is a hell of a lot faster than my old workflow, which involved manual fileZilla and a noobier me developing on a password protected subdomain.
Is there a way I should be doing this so that I'm not waiting for the builds to happen - it seems unnecessary? E.g. use a dummy index.html that temporarily links to the src/main.js until i'm ready to build and deploy the bundled version on to my domain?
This is the current index.html of the boilerplate:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example for Three JS</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<div id="homepage"></div>
<script src='build/main.js'></script>
<script>
const app = new LIB.App;
app.init();
</script>
</body>
</html>
And here is what my rollup config file looks like:
import resolve from '#rollup/plugin-node-resolve'; // locate and bundle dependencies in node_modules (mandatory)
import { terser } from "rollup-plugin-terser"; // code minification (optional)
export default {
input: 'src/main.js',
output: [
{
format: 'umd',
name: 'LIB',
file: 'build/main.js'
}
],
plugins: [ resolve(), terser() ]
};
I tried just switching out the script source from
<script src='build/main.js'></script>
to
<script src='src/main.js'></script>
and removing:
<script>
const app = new LIB.App;
app.init();
</script>
But this didn't work - so i'm here looking for input.
The 'answer' is that I should have been using a dev and prod version of my rollup builds. The dev version should have minification removed.
From Documentation:
You can, if you like, specify a different config file from the default rollup.config.js:
rollup --config rollup.config.dev.js
rollup --config rollup.config.prod.js

Vue.js, vue-cli 3.0 and Google Webfonts

I'm COMPLETLY LOST about including Google Fonts into my project.
I've installed google-fonts-webpack-plugin and tried to configure it properly, but the html is not being injected. Or maybe I'm not thinking about it right. Regardless, how to I include Google Webfonts?
Code in my vue.config.js:
const GoogleFontsPlugin = require("google-fonts-webpack-plugin")
module.exports = {
configureWebpack: {
plugins: [
new google-fonts-webpack-plugin({
fonts: [
{ family: "IBM Plex Sans" }
]
})
]
}
}
Go to the end of app.vue and add below code:
<style lang="scss">
#import url("https://fonts.googleapis.com/icon?family=Material+Icons");
</style>
That plugin is not currently compatible with the version of Webpack used by vue-cli.
What I've usually done in the past is just include the fonts via <link> tags in the index.html file, eg
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>vue</title>
<link href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans" rel="stylesheet">
You could also edit the <style> block in your App.vue component to include
#import url("https://fonts.googleapis.com/css?family=IBM+Plex+Sans");

Avoid including bootstrap min.css & .css with wiredep

I'm writing a script with wiredep & gulp but I have a an unexpected result at the the end when I include Bootstrap:
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap-theme.css" />
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap-theme.min.css" />
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css" />
Why wiredep is including both .css & min.css files? And why bootstrap-theme is also included?
Thanks
The problem came from a bad override in my bower.json:
Before it was:
"overrides": {
"bootstrap": {
"main": [
"dist/js/*.*",
"dist/css/*.*",
"dist/fonts/*.*"
]
}
Fixed one is:
"overrides": {
"bootstrap": {
"main": [
"dist/js/bootstrap.js",
"dist/css/bootstrap.css",
"dist/fonts/*.*"
]
}
This overrides is needed for 3.3.5 and should not be needed anymore with 3.3.6.
I use bindep instead wiredep. It is more professional , with many features but above all it permits to overcome the bower limits using bower.
npm install bindep

ReferenceError: videojs is not defined

I am using video.js (in CDN-Mode) and everything seems to work fine (with Firefox 26.0). The video is embedded and works fine. But when I want to access the video-Object, I'm getting the console-error:
ReferenceError: videojs is not defined on the code-line where I want to access the object:
var myPlayer = videojs('example_video_1');
Googling arround could not solve my problem. I saw implementations where users used: V as constructor instead of videojs but this did not solve my problem).
This is my script, where I want to access the object:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = videojs('example_video_1');
});
</script>
This is my header
<link href="http://vjs.zencdn.net/4.5/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.5/video.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.js"></script>
And this is my video-declaration
<video id="example_video_1" class="video-js vjs-default-skin" controls
preload="auto" width="1270" height="720" poster="videos/search.png"
data-setup="{}">
<source src="videos/search.webm" type='video/webm'>
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p>
</video>
I would be happy for any kind of support.
A year and a half later and this issue occurred for me as well. I just installed it via npm install --save video.js and moved the file from the dist folder into my public scripts folder and it worked.
You must install or use from #videojs/http-streaming. I had same problem and solved by it.
I just made sure that the video.js file was the last attached script tag in the HTML. It worked for me.
import videojs from 'video.js';
try:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = window.videojs('example_video_1');
});
</script>
add the event listener 'DOMContentLoaded' before calling the videojs object:
window.addEventListener('DOMContentLoaded', (event) => {
videojs('element-id', {
controls: true,
autoplay: false,
preload: 'auto'
});
});