How to use CDN in vue cli? - vue.js

I am not familiar with packing frontend projects. When I was writing frontend, we just used JQuery. So the problem is now I have a project created by vue-cli and packed by webpack.
But as I don't want to load libraries from my local server but from remote CDN. How should I change the yarn add dependencies into CDN based form during yarn build? What is the correct way to do this kind of packing?
I've searched a lot but cannot find a good solution, some may suggest adding all CDN in the head section. But that's difficult to manage.

1. update your public/index.html adding the vue script source for the cdn (preferably in the head)
<script src="https://cdn.jsdelivr.net/npm/vue#2.6"></script>
2. create a vue.config.js file in the project root with the following configuration. (if you already have the file, add configureWebpack block to it)
module.exports = {
configureWebpack: {
externals: {
Vue: "vue"
}
}
};
this will flag the Vue dependency as a global, and not add it into the vendor bundle. You can do the same with other dependencies like element-ui, vuetify, vuex, etc...

Related

Assets in Vue app not loading when published to Github pages

I'm publishing my SPA that I'm making with Vue and Buefy to my a gh-pages branch a of private repo, just so I can test if everything will load normally.
Later, I'll upload the finished website to the actual public repo, which is tied to my custom URL (I'm redesigning the website from scratch, using a diff tech).
Since Vue websites needs to be built for distribution, I'm using an NPM package to do this for me: https://github.com/KieferSivitz/vue-gh-pages
"deploy": "node ./node_modules/vue-gh-pages/index.js --branch gh-pages -m \"Deploy to gh-pages.\""
When deploying the website, it loads only partially. The images won't load, and the router will not work (links to other pages won't work).
I'm storing images in the assets folder, and using require('#/assets/logo.png') to load them (at least it works with localhost).
The images are trying to be loaded from https://<username>.github.io/img/logo.d2151712.png.
I read that I would need to set the publicPath to my project name, since currently the website is being served from https://<userName>.github.io/<projectName>/, but with that, the whole website is 404-ing.
With that property, the whole website would try to load from https://<username>.github.io/<projectName>/<projectName>.
I think that somewhere, there's a setting adding <projectName> to router, but not adding elsewhere.
Edit
I tried to force vue-router to get the correct base, without setting the publicPath:
base: "<projectName>/", //process.env.BASE_URL,
But the routes are stil not working, since I'm lazy loading them using import("#/views/Page.vue").
It seems that your issue is, that you want to run your Vue app in a subfolder of a domain (domain.com/subfolder/index.html). This needs to be configured in Vue CLI. Add a new file to the root of your repository, called vue.config.js and add the following content:
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/subfolder/' : '/',
};
This will set the webpack publicPath to /subfolder/ when running the build process in production mode. If you are using Vue CLI < 3.3, you need to use baseUrl instead. You need to make sure, that your path starts with a slash.
See also the documentation of publicPath.
Vue CLI has also a special section for the deployment to GitHub pages. You might also want to take a look at this: https://cli.vuejs.org/guide/deployment.html#github-pages
I read that I would need to set the publicPath to my project name, since currently the website is being served from https://.github.io//, but with that, the whole website is 404-ing.
Indeed, the publicPath property is required to be set to the GitHub repo name, surrounded by slashes (i.e., /github_repo_name/). The 404's are caused by vue-gh-pages removing the leading slash from URLs in index.html:
<!-- <script src=/github-pages-vue-demo/js/chunk-vendors.c4b075fb.js></script> --> <!-- before -->
<!-- <script src=/github-pages-vue-demo/js/app.9b45ea45.js></script> --> <!-- before -->
<script src=github-pages-vue-demo/js/chunk-vendors.c4b075fb.js></script>
<script src=github-pages-vue-demo/js/app.9b45ea45.js></script>
With that property, the whole website would try to load from https://<username>.github.io/<projectName>/<projectName>.
That's a side effect of the slash-removal, making the URLs relative. Relative URLs are relative to the current location (appended to the current directory). For example, with this GitHub pages URL - https://tony19-sandbox.github.io/github-pages-vue-demo/, a relative URL of github-pages-vue-demo/js/app.9b45ea45.js would resolve to:
https://tony19-sandbox.github.io/github-pages-vue-demo/github-pages-vue-demo/js/app.9b45ea45.js
And an absolute URL of /github-pages-vue-demo/js/app.9b45ea45.js would resolve to:
https://tony19-sandbox.github.io/github-pages-vue-demo/js/app.9b45ea45.js
I think that somewhere, there's a setting adding <projectName> to router, but not adding elsewhere.
vue-router has a base property for that purpose, but Vue CLI (#vue/cli-plugin-router) correctly defaults it to process.env.BASE_URL. That environment variable is already equal to publicPath from your Vue CLI config, so there's no need to set it.
Workaround
If you wish to continue using vue-gh-pages, you could use patch-package to disable the slash-removal (index.js line 109) as shown below:
//editForProduction();
if (repository !== null) {
pushToGhPages();
}
GitHub demo
Otherwise, I would skip that library entirely, and use gh-pages directly in a deploy script.
Vue has a configuration for that. If you use vue client then add vue.config.js the next lines por public path property
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './':'/' };

Injecting css link in Vue CLI build output

So this is a project in Laravel with Vue+Vuetify frontend. I'm using Vue CLI. I have set Vue CLI's output directory to Laravel's public folder using vue.config.js, like this:
module.exports = {
configureWebpack: {
devtool: 'source-map'
},
devServer: {
proxy: 'http://localhost:8080/api/v1/',
},
outputDir: '../public',
indexPath: '../resources/views/index.blade.php',
}
This works. However mdi icons on the web page do not show. I understand that I need to add link tag <link href="https://cdn.jsdelivr.net/.../materialdesignicons.min.css" rel="stylesheet"> to the index file, but I don't know where do I add it. The index.blade.php is overwritten by the Build process every time.
Alternate path is to include that css file in the build process by installing npm package and adding a few lines to my main.js, but I'd rather avoid that since my output is already getting bigger.
Figured out soon after posting question. I'll post it here for my own record and for anyone else landing here.
The solution was simpler than I anticipated. Vue CLI uses contents of /public folder to generate build output. So the solution was to simply go to public/index.html and place the meta tag in there.
Note: In my case I created a Laravel project and then used Vue CLI to create a Vue project inside Laravel project folder, so my folder structure looked like this:
Laravel_Project
--app
--bootstrap
--...
--public
--Vue_CLI_Project
----src
----public
Note that there are two public folders: First one is in Laravel project's root directory, whereas the second one is inside Vue project's directory. We are talking about the second one here.

How to have a Nuxt.js and a bare Vue.js project share components

I want to create a website with two separate applications which share some components and store.
index is the public application where I want to use nuxt.js to have SSR.
admin should be a classic SPA where SSR is not needed.
My first idea was to create a multi-page vue application as described in the vue-cli docs at https://cli.vuejs.org/config/#pages
However I'm unsure if this feature fits my needs and if it's possible/advisable to have a nuxt.js app alongside a bare vue.js application, because nuxt.js has a different project structure.
Is there any way to configure nuxt.js so it fits in the default project structure of vue or to configure vue to use the nuxt.js folder structure?
Create multiple Vue Applications with (some) shared source-files (components/store/mixins/etc)
It is easily possible to share resources across multiple Vue-Apps simply by importing the respective resource everywhere you would like to use it, e.g.:
// in /components/MyComponent.vue
<template>
<div>I'm a shared component</div>
<template>
// in /user-app/entry.js
import MyComponent from '../components/MyComponent';
Vue.component('MyComponent', MyComponent);
new Vue({...})
// in /admin-app/entry.js
import MyComponent from '../components/MyComponent';
Vue.component('MyComponent', MyComponent);
new Vue({...})
Where it becomes a little bit complicated
To actually create the seperate apps you will have to use some built-process. By far the most common tool to build Vue apps (and the one used by VueCLI & Nuxt) is WebPack.
To create multiple apps with WebPack you need to do one of two things:
simply use the integreated build-processes of the VueCLI and Nuxt separately. It will work out of the box.
create your own WebPack configuration & the EntryPoint of every single app in WebPack's configuration. NOTE: It is not trivial to use your own build-process for Nuxt, if you really want to use Nuxt I advice you against it. Run with two seperate build-processes instead.
The WebPack configuration itself is a JavaScript Object. The relevant key to declare your EntryPoints is sensibly called entry. Here you specify the name of your EntryPoint and the corresponding path (the path to the entry-file).
The 'Pages' feature of the VueCLI uses this under the hood. However, I believe it is very well worth it to learn how to use WebPack yourself. It is not that complex and will significantly benefit most or all of your JavaScript projects.
A basic example configuration could look like this:
// in webpack.config.js
module.exports = {
mode: 'development',
entry: {
admin: path.resolve(__dirname, './admin-app.js'),
user path.resolve(__dirname, './user-app.js'),
},
// other config
}
WebPack is very well documented: https://webpack.js.org/concepts/

How to use base64-inline-loader in Vue CLI project to embed font files in CSS?

I am importing some custom font files into scss file for a vuejs project. When build, it creates these font-related files in /dist folder, along with app.js and app.css files. The files include font-name.ttf, font-name.woff, font-name.woff2 and font-name.svg
I want to embed these font files in app.css file as in base64 data uri when project build.
There is an npm package named base64-inline-loader and this seems to be a good choice for my problem.
The documentation of the package indicates a method of using it with webpack config. Since my project is using vue-cli 3 and vue-cli-service to run build commands, I know I need to use vue.config.js file to properly config base64-inline-loader.
I am not a big webpack expert and only knows basic concepts of it. I am having trouble in configuring the package in vue.config.js file.
Hope there is somebody who already has some experience of using the same package preferably in Vue.js project.
Please provide me with the vue.config.js file that works :)
As seen from default Vue CLI webpack config, webpack processes font through url-loader:
webpackConfig.module
.rule('fonts')
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
.use('url-loader')
.loader('url-loader')
.options(genUrlLoaderOptions('fonts'))
So first off you need to delete previous loaders applied to that rule, and set up needed(base64-inline-loader).
module.exports = {
chainWebpack: config => {
const fontsRule = config.module.rule('fonts')
// clear all existing loaders.
// if you don't do this, the loader below will be appended to
// existing loaders of the rule.
fontsRule.uses.clear()
config.module
.rule('fonts')
.test(/\.(ttf|otf|eot|woff|woff2)$/)
.use('base64-inline-loader')
.loader('base64-inline-loader')
.tap(options => {
// modify the options...
return options
})
.end()
}
}
P.S. Helpful links:
Related question.
Replacing Loaders of a Rule.
Adding a New Loader.

Disable PWA plugin in Vue CLI 3

I'm having some issues with caching my files using the default service worker that comes with VueCLI 3. I would prefer to just use the default browser caching mechanism, but can't seem to disable the PWA plugin as its not in the vue.config.js file. Passing a blank object to the pwa option doesn't work either as the object is merged and not overwritten.
I resolved this by doing the following:
Removing the registerServiceWorker.js file
removing the import of registerServiceWorker.js from main.js.
removing the PWA plugin from the devDependencies in package.json.
Vue enabled a method to disable pwa for certain builds in version 4. Now you can add --skip-plugins pluginname during your build. This one worked for me just fine:
npx vue-cli-service build --skip-plugins pwa,workbox
Ref: https://cli.vuejs.org/guide/cli-service.html#skipping-plugins
There is an open but accepted proposal to add this to the core functionality:
https://github.com/vuejs/vue-cli/issues/3830
EDIT:
Via command line:
https://cli.vuejs.org/guide/cli-service.html#skipping-plugins
npx vue-cli-service build --skip-plugins pwa,workbox
Via vue.config.js:
module.exports = {
chainWebpack: config => {
config.plugins.delete('pwa');
config.plugins.delete('workbox');
}
}