How to use a template HTML with Snowpack 3? - snowpack

I am new to Snowpack and I have a Template.html' file in my source folder that I would like Snowpack to read and produce an index.html` in the destination output folder. It would also be nice if I can use some variables in the template that Snowpack would simply substitute from the environment or configuration file. Any idea how to achieve this?

If I understand correctly, you are looking to use an alternative to index.html. I'm not sure if you are using react or a different framework, but in case you are using react, I found a solution.
This context is for flavor and is not related to the question, but I'll share in case it is helpful to others. In my case, I wanted to block the following warning on my production build (due to react-scripts, not snowpack):
Loading module from “http://localhost:3000/dist/index.js” was blocked because of a disallowed MIME type (“text/html”).
This is because snowpack requires the following script tag in index.html to generate your pages:
...
<script type="module" src="/dist/index.js"></script>
...
I don't need snowpack in production at this time ---I'm just here for the module hot reloading for now --- so I want to suppress this warning with an alternative index.html file, just for snowpack so that it has this script tag.
Solution:
So for your case where you want to use variables in snowpack --- but not your production build (or other run scripts for that matter) --- you can do the following:
Create a template with the above script in your index.html body, plus whatever other vars you need. Name it something other than "index.html". I went with indexsnowpack.html for simplicity.
Add the following route (Docs here) to your snowpack.config.js file in your apps root directory:
module.exports = {
...
routes: [
{
match: "routes",
src: ".*",
dest: "/indexsnowpack.html"
}
]
...
}
BEWARE: The above solution will match all paths to your new indexsnowpack.html file. So if you are not using a single-page application setup, you'll run into some hiccups. Further, if you have other routes defined (e.g., for api calls), place those above this route so that this route functions as a fallback for all calls except your api.

Related

Static site generation with Nuxt.JS using relative paths

I'm using Nuxt 2.15.8 to generate static pages (migrating to Nuxt 3 is also an option for me if it solves the problem).
It works great when deployed in the root folder of the server but I need it to be served in a subdirectory, like:
https://my.domain.com/folder/subfolder
The problem is that the compiled HTML includes nuxt related assets like:
/_nuxt/123456789.js
which translates to:
https://my.domain.com/_nuxt/123456789.js which obviously fails as the file is in a subfolder, not in the root.
I tried using publicPath config and absolute paths but it is not an option for me as I have several environments with different URLs.
I need to generate static HTML files with relative paths in order to make sure my site works as expected in all the environments, agnostically from the server URL.
I was able to achieve it using Vite + Vue 3 but migrating to a new implementation is not an option, I need to achieve it using the current Nuxt implementation.
I tried using nuxt-vite https://vite.nuxtjs.org/ but was not able to achieve relative paths, I still get
/_nuxt/123456789.js
instead of
./_nuxt/123456789.js
../_nuxt/123456789.js
../../_nuxt/123456789.js
, etc
It seems like it's not supported in plain nuxt 2 but if you use nuxt-vite you can set vite.base to '' or './' in nuxt.config to make the paths relative.
Try this out:
export default defineNuxtConfig({
app: {
baseURL: '/mydir',
buildAssetsDir: '/mydir/_nuxt/',
},
Or just edit index.html manually...

external .env for bundled vue-cli SPA

I tried to use dotenv-webpack, but the .env also included in the bundle.
What I wanted to do is to make the .env readable after the build.
static/
index.html
.env
is this possible on spa's?
No, this is not possible with the standard Vue-CLI/Webpack unless you search inside the bundled gibberish of your code.
If your intention is to do something with the bundled data like changing values inside your .env then there is a way to hook your app with a env.js file, but this should not contain sensitive data.
Explanation of post- "env.js" hook:
you have to check for a global variable somewhere in you code.
i make a example of changing the axios baseURL after bundling the project.
place a js file like "env.js" in the first place of initialization in your web server.
// env.js
document.env = 'https://www.use-other-api.com'
so "document.env" is now declared before your app runs
then you have a hook in your project which is prepared for this "after bundled env changes"
like:
if (document.env === 'https://www.use-other-api.com') {
// change axios baseURL to "document.env"
} else {
// stay default baseURl
}
and that's it.
just be aware of not using any sensitive data in this scope because it is accessible anywhere in your app.
like i would not recommend you to put in some secrets depending in your backend stuff.
No, the .env file should be loaded on the server that runs your app. That's what it's name stands for. It consists of enviromental variables that you can use globally.
You can find more...
https://codeburst.io/process-env-what-it-is-and-why-when-how-to-use-it-effectively-505d0b2831e7

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.

Vue-cli 3 Environment Variables all undefined

I've tried all of the solutions out there but none seem to work for me. I just want to store some values in a .env file within my Vue app but simply trying to log process.env returns an empty object from within the component.
My .env file
VUE_APP_URL={api url}
VUE_APP_TOKEN={token}
My plan was to set these environment variables to data properties but it always returns undefined. If I do console.log(process.env.NODE_ENV) from webpack.config.js it will show that I'm in development but if I tried doing the same from within the component like
mounted() {
this.$nextTick(() => {
console.log(process.env.VUE_APP_URL);
})
}
It just returns undefined.
A few tips for people who land here:
Make sure your .env files are in the project root folder (and not in say src/)
Variable names should start with VUE_APP_ if to be statically embedded into the client bundle
Restart the dev server or build your project for changes to take effect
If you are migrating from a webpack based solution make sure that you replace : (from JSON config) with = (dotenv format). Easy to miss
Make sure you've saved any changes to your .env files.
In old Vue versions environment variables were defined in e.g. config/dev.env.js instead of the .env files in root
I figured it out - I had to install dotenv-webpack and initialize it in webpack.config.js which is odd because none of the docs stated that I needed to do so.
Install dotenv-webpack and configure the vue.config.js file as follows.
npm install dotenv-webpack --save-dev
Add this to your config file:
const Dotenv = require('dotenv-webpack');
module.exports = {
configureWebpack: {
plugins: [
new Dotenv()
]
}
}
In your .env file make sure you add VUE_APP_ before your variables like this:
VUE_APP_VAR1=example
VUE_APP_VAR2=value
Now you can access these variables in your Vue application:
console.log(process.env.VUE_APP_VAR1); // "example"
console.log(process.env.VUE_APP_VAR2); // "value"
Here some links for reference:
https://www.npmjs.com/package/dotenv-webpack
https://cli.vuejs.org/guide/webpack.html
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
so I use
VUE_APP_API_URL (this doesn't work)
then I change it to
VUE_APP_APIURL (this works)
hope it helps
If your vue-cli version is higher than 3.x and you put your .env files in root directory like said in comments. Than you can access your environmental variables from components (like this process.env.VUE_APP_YOUR_VARIABLE).
As said in vue-cli docs
Only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. You can access
them in your application code: console.log(process.env.VUE_APP_SECRET)
I put my .env file in the root directory and appended each variable with VUE_APP_.
To demonstrate this, for example, if the variable you want to use is API_BASE_URL
In your .env file, you put the variable as VUE_APP_API_BASE_URL=baseurl/api/v1
To access it in your files, you do process.env.VUE_APP_API_BASE_URL.
CAVEAT:
Never put any sensitive information you don't want anybody to see, on your front-end. The most common thing you won't want anybody to see (as regards web development) is your API Key. There are real consequences to doing this. This is one such example of someone who has been burned exposing API keys to the public.
However, even if you put your sensitive data in a .env file and add the .env file to a .gitignore file (hence not pushing it to a Git repository hosting service e.g Github, BitBucket, Gitlab etc.), your data is still not safe on the front-end. It's only safe when this is done on back-end code as it will be hosted on a server.
In the front-end, anyone who is determined enough can find your sensitive information. All your information is available on a browser and all that person needs to do is to open the dev tools and check the Sources tab, and BOOM all your sensitive information is laid bare.
Environment variables on the front-end are only useful when you want one reference point for NON-SENSITIVE information, such as a BASE URL, as seen in the example above. A BASE URL can change during the course of development and you won't want to change all references in the application folder manually. It is tedious plus you may miss a few, which would lead to errors.
If you want to avoid exposing your API keys and other sensitive information you may require on the front-end, take a look at this article.
This is what worked for me. I previously created my .env.development and .env.production files in the root folder by manually by right-clicking in the Exploer in VS Code and adding a new file. This kept giving me undefined.
I deleted the files and first installed npm install touch-cli -g
Once installed, i added the environment files as such touch .env.production and touch .env.productionand itworks. So I think there's a difference between how these env files are generated.
NOTE: I do not have webpack installed. Just using the vue cli to build
VS Code ExplorerChrome Developer Tools
IF you are using VITE, use VITE_ in stead of VUE_APP
Vue CLI dotenv usage suffers the inability to provide the .env variables other than prefixed with VUE_APP_. This is OK but this is far not enough to satisfy any even little serious web project that wants to conveniently and securely manage its (sometimes huge) list of variables for different environments.
Here is the solution that makes use of .env variables as convenient as on backends with dotenv.
With this solution you could access your MY_EXTERNAL_API_KEY from your .env[.environment] file in your code like this const key = process.env.MY_EXTERNAL_API_KEY.
It provides:
The convenience of using non-prefixed with VUE_APP_ variables' names and use .env variable expansion feature (use ${VARNAME} kind of variables)
The necessary security: your variables are neither available at browser console with console.log(pocess.env.MYVAR) at run time nor are explorable via text search by their names from .env files within the built application's JS bundle.
You can still use original Vue CLI solution along;
For this use dotenv-webpack plugin in your vue.config.js as follows:
const Dotenv = require('dotenv-webpack');
const envPath = function() {
return (!process.env.NODE_ENV || (process.env.NODE_ENV === 'development')) ?
'./.env' :
`./.env.${process.env.NODE_ENV}`;
}
const dotenvArgs = {
expand: true,
path: envPath()
};
module.exports = {
//... some other config here
configureWebpack: {
plugins: [
new Dotenv(dotenvArgs)
]
}
};
Here:
expand: true allows for ${MYVAR} variables expansion;
path: envPath() allows to define custom .env file name depending on your Vue CLI project environments, and the path depending on you project structure;
There are other useful dotenv-webpack options you could use.
I believe this solution is good enough to fully satisfy most frequent use cases.
NB: Remember as you pass your secret variables set via .env into HTTP requests from your front-end (e.g. an API key in a call to some external API) they are visible to any one who knows where to look. To diminish security risks for this situation there are different solutions.
Just to hint you have either to:
provide only publicly open data via your application;
or authenticate your application (or parts of it) via some authentication service (login/password + JWT|sessions, external authentication providers e.g. Facebook, Google etc.);
or resort to server-generated application.
But this is the whole separate subject.
if you are cominng from VUE-cli-2 or you just cloned/installed an old vuejs project and you can't find .env file, this article explains what you have to do to set your .env variables as they environment files are probably located in config/dev.env.js (Note: this is peculiar to Vue-cli-2 files)
Here is also a solution and a detailed explanation for Vue-cli-3 .env related issue
What worked for me was changing from .env to .env.local. Haven't investigated WHY but I checked an old project and saw that I had a .env.local instead and did same for this project that would not pick the values from .env irrespective of whether vars where prefixed with VUE_APP and it worked.
It seems environment variables are not accessible in child Vue components. Best to declare them globally in main.js with Vue.prototype.env = process.env;
I know that this question was asked about vue-cli 3, which generates code for Vue 2. But it is the top result if you google for "vue3 does not embed env" and similar queries, so I assume that a lot of people end up here when having trouble with process.env variables being undefined in their Vue 3 app.
So this is an answer about how to fix your Vue 3 env issues.
This is what causes the confusion
If you google for env problems with vue, you end up in the vue-cli docs. But vue-cli was replaced by create-vue in Vue 3. There is a alert box at the top of the page that tells you this, but you've probably missed it.
If you did not miss it and followed one of the two links in the box, you ended up in the Vue 3 tooling guide or in the create-vue repo. None of those resources mention env variables. But you learn that create-vue is based on Vite.
If you follow that lead and google for "vite env", you end up in the vite documentation, where you finally find the answer:
env variables have to be prefixed with VITE_ to be compiled into the app (as opposed to VUE_APP_ in vue 2)
env variables will be available in import.meta.env in your app (as opposed to process.env in vue 2)
The latter one is what took me the longest to figure out.
This is how you need to do it
in an .env file in your project root:
VITE_MY_ENV_VAR=foo
The docs will also tell you about the different naming patterns for .env files in Vite. Very useful information if you work with different environments!
in your app:
const my_env_var = import.meta.env.VITE_MY_ENV_VAR
I hope this saves someone the time for figuring this out.
It might also help: make sure your .env files are in lowercase letters because in Linux it won't work even if it is working in windows
The answer provided here helped me out. I'm using Laravel with an odd setup for Vue 2.x. The project is also using Laravel Mix. Here's the solution:
Inside of your .env file, which is a sibling of package.json:
MY_ENVIRONMENT_VARIABLE=my_value
Inside of webpack.mix.js:
const { mix } = require('laravel-mix');
mix.webpackConfig(webpack => {
return {
plugins: [
new webpack.EnvironmentPlugin (
['MY_ENVIRONMENT_VARIABLE']
)
]
};
});
Afterwards, an npm run dev or npx mix should allow you to use these variables.
Credit: Thorsten Lünborg