Can't get Vite to build app and js file into the same dist - vue.js

I'm having trouble configuring vite.config.js so that I can have both my Vue app and a service worker file live in the dist folder. My service worker was working with webpack previously but I've just upgraded to Vite and I'm having trouble configuring the build. My goal is to have my dist folder look like:
dist
|- index.html
|- sw.js
|- assets
|- app.[hash].js
I tried various different configurations but none of them have worked:
An approach that is recommended by Workbox. It seems like this doesn't work because of what is mentioned in this comment.
After reading that comment I tried to separate the logic out into a separate file (vite-sw.config.js) and running vite build -c vite-sw.config.js. This successfully generated the file I wanted but I couldn't figure out how to get that file mixed in with the original build. Is there a way to combine vite build and vite build -c vite-sw.config.js so that they both output to the same dist directory without overriding each other?
I found this alternative approach which successfully created the folder structure I wanted in dist but I was unable to adjust the format of the service worker file so I got Cannot use import statement outside a module (at sw.js:1:1) in the browser. Is there some way to use this method and somehow configure the format of the service worker file?
Any other ideas? I've been pretty stuck on this for a while. Thanks!

Try changing your configuration like this:
export default defineConfig({
build: {
rollupOptions: {
output:
{
format: 'es',
strict: false,
entryFileNames: "[name].js",
dir: 'dist/'
}
}
},
.
.
.
});

Related

How can I copy a *.html file in /dist folder when using vue-cli-service build --target lib?

While I clearly am no webpack expert, I usually figure/find out what I need to modify in order to achieve what I need. However, I lost more than a day on this one, even though it seems fairly simple:
I want to add an index.html to the build, after building, by copy-ing it from a folder.
I tried adding this to configureWebpack, in vue.config.js:
plugins: [
new CopyPlugin([{
from: 'deploy',
to: '/',
force: true,
copyUnmodified: true
}])
]
(the only file in deploy folder is this index.html).
I also tried various versions of chainWebpack, mostly picked from github discussions, trying to tap into plugins like html, move-index and copy. However, most of what I found on github breaks the build for me.
Not even simple attempts, where I just try to tap and console don't seem to work:
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
console.log(args);
return args;
});
},
outputs:
Building for production as library (commonjs,umd,umd-min)...[]
ERROR TypeError: Cannot read property '__expression' of undefined`
...
at module.exports.toConfig (D:\sgn\www\_g\berwow\BERWoW\Client\RecommenderV2\node_modules\webpack-chain\src\Config.js:129:40)
What I figured out so far:
CopyPlugin either doesn't work or it has an exception for .html files.
There're are at least two plugins: (move-index & html) which probably interfere with my copy. I haven't figure out how to push my change to the back of the queue.
I also tried with a test.html and I also tried placing a different extension on my file .txt and overriding it when copying it, back into .html. Most times I end up with errors.
Is there a relatively straight forward way to tap into vue-cli-serve's build command and simply copy an index.html to the folder?
The build command I'm using is:
vue-cli-service build --target lib --name SomeName --inline-css --inline-vue src/main.ts
Please note it's a --target lib build, which doesn't output an index.html into the dist folder, but a demo.html. So I'd advise testing any solution against a --target lib build, as it clearly has a different output than normal builds.
Here's the output of vue inspect: https://jsfiddle.net/websiter/rkh5ecvd/embedded/js/dark/#JavaScript
and here's the current contents of my vue.config.js: https://jsfiddle.net/websiter/fou3y4zc/embedded/js/dark/#JavaScript , where configWebpack and chainWebpack are attempts at addressing/peeking into the above issue.
I'm using #vue/cli 4.2.3 and vue 2.6.11 with webpack 4.42.1
I figured out a way around it, by simply running npm i copyfiles -D and adding this bit to the build script:
&& copyfiles -f ./deploy/* dist/Recommender
It's not a proper answer to the problem, it's a way around it. But it works :).
Still interested in how this could be chained to the webpack build script properly.
I know this is an old issue, but I figured I'd add some more details for anyone still having issues with this in Vue 3.
I was able to achieve a similar output with vue 3.0.0, #vue/cli-service 4.5.0, webpack 4.46.0 and copy-webpack-plugin 6.4.1 using the following configs:
vue.config.js
const CopyPlugin = require("copy-webpack-plugin");
/**
* #type {import('#vue/cli-service').ProjectOptions}
*/
module.exports = {
chainWebpack: (config) => {
// Disable HTML Generation.
config.plugins.delete("html");
config.plugins.delete("preload");
config.plugins.delete("prefetch");
// Copy all contents of the "static" src directory
// to the destination's root.
config.plugin("copy").use(CopyPlugin, [
{
patterns: [{ from: "./static", to: "./" }],
},
]);
},
};
npm script:
vue-cli-service build --target lib --inline-vue --name app src/main.js
Note: the "inline-vue" argument forces embedding Vue into the bundle (see https://cli.vuejs.org/guide/build-targets.html#library).

Vue.js configure root directory when building for production

I am using vue cli 3.6.3.
How can i build a Vue.js project for production if the project is not in the web root?
Inside the webserver the project directory is "my/web/directory"
I start the project using webpack template, and set the publicPath and ROOT_API variables:
config/prod.env.js:
'use strict'
module.exports = {
NODE_ENV: '"production"',
ROOT_API: '"http://www.example.com/my/web/directory/myapi/myindex.php"',
publicPath: '/my/web/directory/'
}
After a npm run build i do upload the dist files (just inside the dist folder: static and index.html) the project point to the webserver root and did not find the js files.
How can i point to the right directory path?
I just find the assetsPublicPath inside the build section of the config/index.js, i do configure and now it is working fine.

Provide enviroment variables for production vue build

I would like to achieve following:
a Vue application is build with npm build,
then the /dist result is copied to some environment
in this enviroment I have some static setting file with name=value settings
the Vue application should read this setting from local folder where it is running or default to some setting
What is the best way to do this.
If you want "to inject" some settings to the bundled app so I think it can be possible only with another js file (globalConfig.js) with global object like:
window.myAppSettings = {
MY_VARIABLE: 'some_value'
}
Which will be copied somehow to your dist folder on a particular environment.
You should also prepare your app to reference that file:
Firstly, add this settings object as external lib in vue.config.js
module.exports = {
chainWebpack: config => {
config.externals({
'my-app-settings': 'myAppSettings'
})
}
}
So you can get your settings in code:
import mySettingsObject from 'my-app-settings'
//...
let myValue = mySettingsObject.MY_VARIABLE
Add reference to globalConfig.js in index.html file in the head section:
<script src="<%= BASE_URL %>globalConfig.js"></script>
Local Development
Probably you will need some default settings to be able to debug your app locally. In this case you can create localConfig.js in your public folder with some default values.
Then change your script in index.html to this:
<script src="<%= BASE_URL %><%= VUE_APP_GLOBAL_SETTINGS_VERSION %>Settings.js"></script>
Then create two files in the project root .env.local and .env.production:
// .env.local
VUE_APP_GLOBAL_SETTINGS_VERSION=local
and
// .env.production
VUE_APP_GLOBAL_SETTINGS_VERSION=global
So when you run npm run serve it will load your local config and your app will load localSettings.js.
And when it builds with npm run build it will load globalSettings.js because building uses a production mode by default.
If you created your project using Vue CLI 3 you can do like this.
Make sure your settings file is named .env and place it in your project root.
In the .env file, your variables should be prefixed with "VUE_APP_"
VUE_APP_SOMEKEY=SOME_KEY_VALUE.
Access them with process.env.*.
console.log(process.env.VUE_APP_SOMEKEY) // SOME_KEY_VALUE
Here's some more info on evironment variables in vue: Vue CLI 3 - Environment Variables and Modes
EDIT:
Sorry. I probably misunderstood your question. This solution will not work if your settings file is in the dist folder.

Configure nuxt.js application to work in a subdirectory on a webserver

I want to deploy a static nuxt.js application (built with nuxt generate) to a subdirectory of a webserver. nuxt places the generated files in the dist directory by default:
If I start a webserver on the parent directory of the dist folder and open the page with:
http://localhost:34360/dist/
the site fails to load the script files from the domain root directory:
I've tried setting the publicPath property in the nuxt config:
build: {
publicPath: '/dist/'
}
The appplication compiles to:
Now, nuxt moves the script files one level lower (/dist/dist) and searches on root level again (/dist), thus still not finding the files
How can I configure the site, such that scripts and assets are loaded and it is self contained, no matter on which directory on my server I put it?
The issue has been covered on GitHub but the suggested hints (using publicPath) didn't work, as shown above.
Sidenote: I do not want to specify the publicPath absolut (i.e. http://localhost:8080/dist), which would work but creates new problems.
You need router/base
router: {
base: '/dist/'
}
To complete #Aldarund answer, I use :
export default {
[…] // some code
router: {
base:
process.env.NODE_ENV === "development" ? process.env.BASE_URL : "/<subfolder>/"
} // where <subfolder> is the subfolder!
};
In Nuxt 3.0 use config's app.baseURL or NUXT_APP_BASE_URL environment variable.

How can I create two separate bundles with vue-cli 3?

I want to build two separate vue apps that will be served on two different routes in an express application: a ‘public’ vue app and an ‘admin’ vue app. These two apps have their own router and store but they share a lot of custom components.
How can I edit the default webpack template to make it output two separate bundles based of my two different entry points (‘public’ and ‘admin’)?
The goal would be to end up with a setup more or less like this:
my-app/
+- ...
+- dist/
| +- admin/ Admin bundle and files
| +- public/ Public bundle and files
+- src/
| +- components/ Shared components
| +- admin/ Entry point, router, store... for the admin app
| +- public/ Entry point, router, store... for the public app
+- ...
Must by available 2 dev servers http://localhost:8080/admin and http://localhost:8080/public
Each project must be in own folder in dist, and own public
What i have today:
created file vue.config.js in root directory
With:
module.exports = {
// tweak internal webpack configuration.
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
chainWebpack: config => {
// If you wish to remove the standard entry point
config.entryPoints.delete('app')
// then add your own
config.entry('admin')
.add('./src/admin/index.js')
.end()
.entry('public')
.add('./src/public/index.js')
.end()
}
}
Assuming you need completely separate builds, with some shared scripts guided by your entries, you can add separate build commands.
In your package.json "scripts" section:
"scripts": {
"build:admin": "vue-cli-service build --dest dist/admin src/admin/index.js,
"build:public": "vue-cli-service build --dest dist/public src/public/index.js
}
For admin builds, you may run:
npm run build:admin
and for public builds:
npm run build:public
For more information, view the build target docs.
I am also very interested by this matter.
Maybe we can solve this issue with subpages :
https://cli.vuejs.org/config/#pages :
"Build the app in multi-page mode. Each "page" should have a corresponding JavaScript entry file. The value should be an object where the key is the name of the entry, and the value is either:"
module.exports = {
pages: {
index: {
// entry for the *public* page
entry: 'src/index/main.js',
// the source template
template: 'public/index.html',
// output as dist/index.html
filename: 'index.html'
},
// an admin subpage
// when using the entry-only string format,
// template is inferred to be `public/subpage.html`
// and falls back to `public/index.html` if not found.
// Output filename is inferred to be `admin.html`.
admin: 'src/admin/main.js'
}
}
Building on the other answers here, I've found it's possible to specify the build output directory in vue.config.js rather than having to do that in the command line. So then combining that with the use of the VUE_CLI_SERVICE_CONFIG_PATH environment variable makes things a lot simpler - no need for it to copy/delete config files each time you build.
You do have to specify the full paths to the Vue config files though. This works even on Windows, but only from a Linux-type terminal (e.g. I tested it from Git Bash installed by Git for Windows and it worked fine, but doesn't work from the normal Windows Command Prompt, as I couldn't find any way of setting the environment variable in the npm script which worked when run from there)
https://gist.github.com/EdwardMillen/0c417747cd8ce64b8ba550bdfa582cf5
It is also possible to have multiple vue.config.js configs and switch them over using the VUE_CLI_SERVICE_CONFIG_PATH environment variable.
For example, we can have a default vue.config.js and an additional vue.public.config.js and run the build like this:
# Build using vue.config.public.js
# Note: using real path here, it didn't work with relative path
CONF=`realpath vue.config.public.js`
VUE_CLI_SERVICE_CONFIG_PATH=$CONF npm run build
# Build using default vue.config.js
npm run build
Where npm run build is defined in package.json as vue-cli-service build:
"scripts": {
"build": "vue-cli-service build"
}
Note: I didn't find any mention on VUE_CLI_SERVICE_CONFIG_PATH in the documentation, found it looking at the source code.