How to use `htmlWebpackPlugin.options.title` inside Vue SFC template? - vue.js

I want to use htmlWebpackPlugin.options.title in SFC template, is that doable?

Yes it's doable ...but other way around
You can use Environment Variables do define your app title
Then you can configure htmlWebpackPlugin to use this ENV variable as the value for title option
At the same same time, you can use use this variable in any client side JS (be it pure JS or SFC). Note that to use it inside the template, it's necessary to assign it
to the data first...
.env file
VUE_APP_TITLE=My App Title
vue.config.js
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = process.ENV.VUE_APP_TITLE
return args
})
}
}
SFC
data() {
return {
title: process.ENV.VUE_APP_TITLE
}
}

document.title will do, Michal's solution will do too in a verbose but more strict and flexible format, see which one works best for you.

Related

How to remove comments in chunk-vendors.js

a little strange question, but how to remove comments from the file chunk-vendors.js? I mean, there are automatically placed licenses and other information about plugins, including the vue, vuex, vue-router.
Is there any parameter responsible for this? Iā€™m tired of removing these lines manually after each build
I use vue-cli
Assuming Vue CLI 3 or newer, this is handled by the minimizer's (terser) output options. Specifically, set output.comments=false to exclude comments from the minified output.
Edit vue.config.js to include:
module.exports = {
chainWebpack: config => {
config.optimization.minimizer('terser').tap((args) => {
args[0].terserOptions.output = {
...args[0].terserOptions.output,
comments: false // exclude all comments from output
}
return args
})
}
}

Nuxt.js env Property, understanding and how to use it?

following https://nuxtjs.org/api/configuration-env
I have been trying to set up my apiUrl in nuxt.config.js once for the whole project, like:
export default {
env: {
apiUrl: process.env.MY_REMOTE_CMS_API_URL || 'http://localhost:1337'
}
}
adding this in nuxt.config.js, I'd expect (and would like) to have apiUrl accessible everywhere in the project.
In particular, it is needed for the 3 following cases:
with axios, to generate static pages from dynamic urls (in nuxt.config.js)
generate: {
routes: function () {
return axios.get(apiUrl + '/posts')
.then((res) => {
return res.data.filter(page => {
return page.publish === true;
}).map(page => {
return {
route: '/news/' + page.slug
}
})
})
}
},
with apollo, to get data via graphql (in nuxt.config.js)
apollo: {
clientConfigs: {
default: {
httpEndpoint: apiUrl + '/graphql'
}
}
},
in every layout, page and components, as the base url of media:
<img :src="apiUrl + item.image.url" />
As you might see, only thing I need is to 'print' the actual base url of the cms.
I have also tried to access it with process.env.apiUrl, with no success.
The only way I was able to make it has been to create an extra plugin/apiUrl.js file, which injects the api url, and seems wrong to me as I am now setting the apiUrl twice in my project.
I asked this question in the past, but in a way less clear way. I was suggested to use dotenv, but from the docs it looks like adding an additional layer of complication that might not be necessary for a simpler setup.
Thanks.
I think dotenv module really is what you need.
This is my setup:
Project root has a .env file that contains
BASE_URL=https://www.myapi.com
require('dotenv').config() at top of nuxt.config.js
#nuxtjs/dotenv installed and added to buildModules of nuxt.config.js
env: { BASE_URL: process.env.BASE_URL} added to nuxt.config.js
axios: { baseURL: process.env.BASE_URL } added to nuxt.config.js (optional)
You should have access to your .env throughout the project. (process.env.BASE_URL)
I haven't used apollo, but you should be able to set the apollo endpoint with process.env.BASE_URL + '/graphql'
As of Nuxt 2.13, #nuxtjs/dotenv is not required anymore. Read here
The concept that I was missing is that you set up the same named variable in your server / pipeline, so that you have your (always local / never pushed) .env file and a same name variable remotely, not added to your repo (where the value can be the same or different)

Vue CLI minifies for production, but how can properties and other definitions also be shortened?

I looked at an output file (e.g. app.4a7888d9.js) that the Vue CLI generated to see what actually got reduced and I saw that properties declared in the 'data' object, methods declared in the methods object, etc. retain their original name. Same with Vuex state properties.
I'm not trying to obfuscate my code entirely but I do use rather long descriptive names which could benefit of minification. Please don't hate, but an example of a worst case scenario of a property name I have is scheduledTransactionConditionActiveComponent
Is there a better way to achieve minification besides what the cli does by default ? If I should use a different package for this, is there one that's proven for vue?
Vue CLI uses terser-webpack-plugin for minification, and property mangling is disabled by default. You could enable it in your Vue config as follows:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.optimization.minimizer('terser').tap(args => {
const opts = args[0]
opts.terserOptions.mangle = {
...opts.terserOptions.mangle,
properties: true, // mangle all property names
}
return args
})
}
}
The Terser docs also recommend selective property mangling (e.g., by only applying it to names that match a regexp). For example, you could configure Terser to only mangle properties that end with an underscore:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.optimization.minimizer('terser').tap(args => {
const opts = args[0]
opts.terserOptions.mangle = {
...opts.terserOptions.mangle,
properties: {
regex: /_$/, // mangle property names that end with "_"
},
}
return args
})
}
}
Note: Although this works well for data props, this mangling does not work for component names (i.e., property names under components).

Vue/Nuxt: How to define a global method accessible to all components?

I just want to be able to call
{{ globalThing(0) }}
in templates, without needing to define globalThing in each .vue file.
I've tried all manner of plugin configurations (or mixins? not sure if Nuxt uses that terminology.), all to no avail. It seems no matter what I do, globalThing and this.globalThing remain undefined.
In some cases, I can even debug in Chrome and see this this.globalThing is indeed defined... but the code crashes anyway, which I find very hard to explain.
Here is one of my many attempts, this time using a plugin:
nuxt.config.js:
plugins: [
{
src: '~/plugins/global.js',
mode: 'client'
},
],
global.js:
import Vue from 'vue';
Vue.prototype.globalFunction = arg => {
console.log('arg', arg);
return arg;
};
and in the template in the .vue file:
<div>gloabal test {{globalFunction('toto')}}</div>
and... the result:
TypeError
_vm.globalFunction is not a function
Here's a different idea, using Vuex store.
store/index.js:
export const actions = {
globalThing(p) {
return p + ' test';
}
};
.vue file template:
test result: {{test('fafa')}}
.vue file script:
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions({
test: 'globalThing'
}),
}
};
aaaaaaaaand the result is.........
test result: [object Promise]
OK, so at least the method exists this time. I would much prefer not to be forced to do this "import mapActions" dance etc. in each component... but if that's really the only way, whatever.
However, all I get is a Promise, since this call is async. When it completes, the promise does indeed contain the returned value, but that is of no use here, since I need it to be returned from the method.
EDIT
On the client, "this" is undefined, except that..... it isn't! That is to say,
console.log('this', this);
says "undefined", but Chrome's debugger claims that, right after this console log, "this" is exactly what it is supposed to be (the component instance), and so is this.$store!
I'm adding a screenshot here as proof, since I don't even believe my own eyes.
https://nuxtjs.org/guide/plugins/
Nuxt explain this in Inject in $root & context section.
you must inject your global methods to Vue instance and context.
for example we have a hello.js file.
in plugins/hello.js:
export default (context, inject) => {
const hello = (msg) => console.log(`Hello ${msg}!`)
// Inject $hello(msg) in Vue, context and store.
inject('hello', hello)
// For Nuxt <= 2.12, also add šŸ‘‡
context.$hello = hello
}
and then add this file in nuxt.config.js:
export default {
plugins: ['~/plugins/hello.js']
}
Use Nuxt's inject to get the method available everywhere
export default ({ app }, inject) => {
inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
Make sure you access that function as $myInjectedFunction (note $)
Make sure you added it in nuxt.config.js plugins section
If all else fails, wrap the function in an object and inject object so you'd have something like $myWrapper.myFunction() in your templates - we use objects injected from plugins all over the place and it works (e.g. in v-if in template, so pretty sure it would work from {{ }} too).
for example, our analytics.js plugin looks more less:
import Vue from 'vue';
const analytics = {
setAnalyticsUsersData(store) {...}
...
}
//this is to help Webstorm with autocomplete
Vue.prototype.$analytics = analytics;
export default ({app}, inject) => {
inject('analytics', analytics);
}
Which is then called as $analytics.setAnalyticsUsersData(...)
P.S. Just noticed something. You have your plugin in client mode. If you're running in universal, you have to make sure that this plugin (and the function) is not used anywhere during SSR. If it's in template, it's likely it actually is used during SSR and thus is undefined. Change your plugin to run in both modes as well.
This would be the approach with Vuex and Nuxt:
// store/index.js
export const state = () => ({
globalThing: ''
})
export const mutations = {
setGlobalThing (state, value) {
state.globalThing = value
}
}
// .vue file script
export default {
created() {
this.$store.commit('setGlobalThing', 'hello')
},
};
// .vue file template
{{ this.$store.state.globalThing }}

Cypress How to store global constants in a file that can be used across all spec files?

I'm looking for a way to store global constants in a file that could be used across all my spec files. Can anyone help?
Use the cypress.json file that is in your project root like this:
{
"env": {
"your_var": "your_value"
}
}
https://docs.cypress.io/guides/references/configuration.html
Once you set some env variables, you can reference them from your specs like this: Cypress.env('your_var');
The following link might help with an easy way to set and get from env variables.
https://docs.cypress.io/api/cypress-api/env.html#Syntax
describe('My First Test', function() {
it('it set value to global variable', function() {
Cypress.env('some_variable', "hello")
})
it('it get value to global variable', function() {
expect(Cypress.env('some_variable')).to.equal('hello')
})
})
I like to create a constants file such as constants.js as an exportable constants object:
export const NAME = {
FIRST: 'John',
LAST: 'Smith',
};
and in my spec files import them: test.spec.js
import { NAME } from '../../support/constants';
describe('Landing page', () => {
beforeEach(() => cy.login());
cy.get(NAME.FIRST).assertion('verify the name');
});
Global variables - sounds like fixtures.
See writefile - JSON - Write response data to a fixture file
cy.request('https://jsonplaceholder.typicode.com/users').then((response) => {
cy.writeFile('cypress/fixtures/users.json', response.body)
})
// our fixture file is now generated and can be used
cy.fixture('users').then((users) => {
expect(users[0].name).to.exist
})
Care to share why you want to do so?
Sounds like it may be interesting.
since cypress is js, it is possible to define const in on js file (my-const.js) as
export const ARE_YOU_SURE='Are you sure';
and use them in another file as
import * as constants from "../[proper path]/my-conste.js";
...
var s = constants.ARE_YOU_SURE + ' about this?'
You can use environment variables stored in either cypress.json or cypress.env.json.
cypress.json
{
"env": {
"myVar": "value..."
}
}
cypress.env.json
{
"myVar": "value..."
}
You can use your environment variable using Cypress.env('myVar').
const myVar = Cypress.env('myVar')
You can review your environment variables in the Settings tab of the cypress runner.