How do you control your publicPath property in vue.config.js - vue.js

I understand how to control what the publicPath would be based on process.env.NODE_ENV variable.
My vue.config.js is working as expected, but only for production and non-production environments. How would I control the publicPath variable when I have qa, dev, and stage environments?
Note: I have added my .env.qa, .env.dev, and .env.stage.
vue.config.js:
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/ProductionEnv/'
: '',
"transpileDependencies": [
"vuetify"
]
}

I would compute publicPath in vue.config.js like this:
function getPublicPath() {
switch (process.env.NODE_ENV) {
case 'production': return '/ProductionEnv/'
case 'qa': return '/QaEnv/'
case 'dev': return '/DevEnv/'
case 'stage': return '/StageEnv/'
default: return ''
}
}
module.exports = {
publicPath: getPublicPath()
}

If you need conditional behavior based on the environment you can use a function and mutate the values inside, or return an object which will be merged.
// vue.config.js
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// mutate config for production...
} else {
// mutate for development...
}
}
}
See more here: configureWebpack

Related

Vue V-Bind:src always includes local server "localhost:8080"

Hi! I receive data from the server by the type "/uploads/image.png", that is, the path to the file. But Vue add to path localhost:8000,
how can I replace localhost with the domain I need?
My problem:
Here
my vue-config:
const path = require('path')
module.exports = {
outputDir: path.resolve(__dirname, './dist'),
devServer: {
proxy : {
'/': {
target: 'http://localhost:1337'
}
}
}
}
set publicPath:
publicPath: process.env.NODE_ENV === 'production' ? '': 'http://localhost:1337/',

Removing all data-test attributes from Vue templates during production build in Vue 3

I work with Vue3 in TS (last vue-cli).
I want to get all nodes (vnodes) elements when vue-loader compile .vue file.
I need to read nodes attributes and remove all "data-test".
I have try in vue.config.js to use :
module.exports = {
chainWebpack: (config) => {
config.module
.rule('vue')
.use('vue-loader')
// .loader('vue-loader') // same with
.tap((options) => {
options.compilerOptions = {
...(options.compilerOptions || {}),
modules: [ // never enter here
{
preTransformNode(node) {
// if (process.env.NODE_ENV === 'production') {
const { attrsMap, attrsList } = node
console.log(node)
if (attrsMap['qa-id']) {
delete attrsMap['qa-id']
const index = attrsList.findIndex(
(x) => x.name === 'data-test'
)
attrsList.splice(index, 1)
}
// }
return node
}
}
]
}
return options
})
}
}
I know the transformation is done inside vue-template-compiler.
How can I enter in compile hook ?
I have try to use preTransformNode in module but that fail.
Sources :
https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler#readme
https://vue-loader.vuejs.org/options.html
The main problem here is that you are working with vue-template-compiler documentation, but that package is the compiler for Vue 2!
In Vue 3, compiler is split into multiple packages and is missing proper documentation as of now (or I was just unable to find it)
Also there were significant changes in the API - instead of modules, you pass nodeTransforms (source) and transforms are not objects, just functions.
Luckily for you, there is a interesting video on YT presented by Vue core member Rahul Kadyan which shows the exact use case you need (removing data-test attributes) - code
So I guess the code should look like this:
function removeDataTestAttrs(node) {
if (node.type === 1 /* NodeTypes.ELEMENT */) {
node.props = node.props.filter(prop =>
prop.type === 6 /* NodeTypes.ATTRIBUTE */
? prop.name !== 'data-test'
: true
)
}
}
module.exports = {
parallel: false, // !!IMPORTANT!! - see note below
chainWebpack: (config) => {
config.module
.rule('vue')
.use('vue-loader')
.tap((options) => {
options.compilerOptions = {
...(options.compilerOptions || {}),
nodeTransforms: [removeDataTestAttrs]
}
return options
})
}
}
Note - the problem mentioned in comments (solution working with serve but throws errors on build) is caused by Vue CLI using thread-loader for production builds. The problem is that while using thread-loader, you can not pass a functions as part of Webpack config (see this warning in the docs) so setting parralel: false is required to make it work....
Vite (Update - 22.06.22)
// vite.config.ts
function removeDataTestAttrs(node) {
if (node.type === 1 /* NodeTypes.ELEMENT */) {
node.props = node.props.filter(prop =>
prop.type === 6 /* NodeTypes.ATTRIBUTE */
? prop.name !== 'data-test'
: true
)
}
}
export default defineConfig(() => {
return {
plugins: [
vue({
template: {
compilerOptions: {
nodeTransforms: isProd ? [removeDataTestAttrs] : [],
},
},
}),
]
}
})
Vue-CLI 5 + Vue 3.2:
const { defineConfig } = require('#vue/cli-service');
function removeAttributesDuringBuild (node) {
const attributesToRemove = [
'data-test',
':data-test',
'v-bind:data-test',
'data-value',
':data-value',
'v-bind:data-value'
];
const nodeIsElement = node.type === 1; // ENUMS ARE STUPID
if (nodeIsElement) {
node.props = node.props.filter(function (prop) {
const propIsAttribute = prop.type === 6; // ENUMS ARE STUPID
const propIsDynamicAttribute = prop.name === 'bind';
if (propIsAttribute) {
const attributeName = prop.name;
return !attributesToRemove.includes(attributeName);
}
if (propIsDynamicAttribute) {
const attributeName = prop.arg?.content;
return !attributesToRemove.includes(attributeName);
}
return true;
});
}
}
module.exports = defineConfig({
lintOnSave: false,
transpileDependencies: true,
parallel: false, // disabled to allow for node transforms
chainWebpack: (config) => {
// Remove comments during build
config.optimization
.minimizer('terser')
.tap((args) => {
args[0].terserOptions.output = {
...args[0].terserOptions.output,
comments: false
};
return args;
});
// Remove dev attributes
config.module
.rule('vue')
.use('vue-loader')
.tap(function (options) {
options.compilerOptions = {
...(options.compilerOptions || {}),
nodeTransforms: [removeAttributesDuringBuild]
};
return options;
});
}
});
Vite 4 + Vue 2.7
import vue from '#vitejs/plugin-vue2';
import { defineConfig } from 'vite';
function removeAttributesDuringBuild (astEl) {
const attributesToRemove = [
'data-test',
':data-test',
'v-bind:data-test',
'data-value',
':data-value',
'v-bind:data-value'
];
function removeAttribute (attributesMap, attributesList, attributeToRemove) {
if (attributesMap[attributeToRemove]) {
delete attributesMap[attributeToRemove];
const index = attributesList.findIndex(function (attribute) {
return attribute.name === attributeToRemove;
});
attributesList.splice(index, 1);
}
}
if (process.env.NODE_ENV === 'production') {
const { attrsMap, attrsList } = astEl;
attributesToRemove.forEach(function (attributeToRemove) {
removeAttribute(attrsMap, attrsList, attributeToRemove);
});
}
return astEl;
}
export default defineConfig(() => {
return {
plugins: [
vue({
template: {
compilerOptions: {
modules: [
{
preTransformNode: removeAttributesDuringBuild
}
]
}
}
})
]
};
});

Vue CLI Service production build without version code?

I have a vue project and I use vue-cli-service build to build the project for production.
I noticed by default when I build the files, the resource name are having some kind of version code like
app.34fc5700.js
chunk-vendors.c7da5824.js
Is there a way to get rid of it?
I'm using vue.config.js, there's no webpack.conf.js in my project, and this is how it looks like:
module.exports = {
publicPath: process.env.VUE_APP_ROOT_PATH,
outputDir: process.env.VUE_APP_BUILD_DIR,
chainWebpack: config => {
config.resolve.symlinks(false);
config.plugin('html').init((Plugin, args) => {
const newArgs = {
...args[0],
};
newArgs.minify && (newArgs.minify.removeAttributeQuotes = false);
return new Plugin(newArgs);
});
},
css: {
loaderOptions: {
sass: {
additionalData: '#import "#/scss/_variables.scss";',
},
},
}
}
Looks like the option filenamehashing is something you need. Basically this option is enabled by default so you might need to turn it off:
// vue.config.js
module.exports = {
filenameHashing: false,
// ...
};

nuxt.config.js where build modules build only in dev mode?

The source code: github.com/alexpilugin/ap-nuxt-firebase-ssr
The issue is next: this Nuxt SSR Application uses the same nuxt.config.js file which is located in /src folder and before deployment it will be copied into the server folder.
nuxt.config.js contains a next build module which creates an issue on server (in the ssrapp firebase function)
buildModules: [
// https://go.nuxtjs.dev/eslint
'#nuxtjs/eslint-module'
],
My question is how to use a single nuxt.config.js file but don't use #nuxtjs/eslint on production?
I found that it's possible to define dev mode in nuxt.config.js file like that:
dev: process.env.NODE_ENV !== 'production'
but how to use it with buildModules in order to use it with a condition?
My current solution - remove #nuxtjs/eslint-module from nuxt.config.js file
I think you can write a javascript function that returns related environment based modules (dev or prod).
// moduleBuilder.js
const getModulesByEnvironment = () => {
const env = process.env.NODE_ENV;
if (env === 'production') {
return [
...
'brilliant_prod_module',
...
];
}
else {
return [
...
'brilliant_dev_module',
...
]
}
};
export { getModulesByEnvironment };
// nuxt.config.js
import { getModulesByEnvironment } from './moduleBuilder';
...
buildModules: getModulesByEnvironment()
...
You could use array and object destructuring together with process.env.NODE_ENV comparison like this:
nuxt.config.js:
const isProduction = process.env.NODE_ENV === 'production'
export default defineNuxtConfig({
modules: [
...(isProduction ? ['nuxt-bugsnag'] : []),
'#nuxtjs/tailwindcss',
'#vueuse/nuxt',
],
...(
isProduction
? {
bugsnag: {
config: {
apiKey: '',
enabledReleaseStages: ['staging', 'production'],
}
}
}
: {}
),
})

vue.js webpack problem: can't add plugin to vue.config.js with configureWebpack

vue.js webpack problem: I can't add a plugin to vue.config.js with configureWebpack
I created a vue.js project with vue cli 3. I am following the example in:
https://cli.vuejs.org/guide/webpack.html
My vue.config.js:
let webpack = require('webpack');
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
__TEST_MESSAGE__: JSON.stringify('howdy there!')
})
]
},
};
The resolved webpack config looks like:
{
mode: 'production',
...
plugins: [
/* config.plugin('vue-loader') */
new VueLoaderPlugin(),
/* config.plugin('define') */
new DefinePlugin(
{
'process.env': {
VUE_APP_CLI_UI_URL: '""',
NODE_ENV: '"production"',
BASE_URL: '"/"'
}
}
),
/* config.plugin('case-sensitive-paths') */
new CaseSensitivePathsPlugin(),
...
/////////////////////////////////////////////////////
// Inserted note for SO: This is messed up! Should
// be:
// new DefinePlugin({ __TEST_MESSAGE__: '"howdy there!"' })
/////////////////////////////////////////////////////
{
definitions: {
__TEST_MESSAGE__: '"howdy there!"'
}
}
],
...
}
configureWebPack is supposed to merge my plugins with the vue defined plugins. Why is it stripping the DefinePlugin class out and just including the argument to the constructor in the plugins array?
Because Vue already includes the DefinePlugin, you need to modify it using Webpack's chain API instead of attempting to add a new one.
module.exports = {
chainWebpack: config => {
config.plugin('define').tap(args => {
args[0].__TEST_MESSAGE__ = JSON.stringify('howdy there!')
return args
})
}
}
This results in the following config (just an example)...
new DefinePlugin(
{
'process.env': {
NODE_ENV: '"development"',
BASE_URL: '"/"'
},
__TEST_MESSAGE__: '"howdy there!"'
}
),
See https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-plugin