5

I have VueJS app (Vue CLI 3) and additional static JS script in public folder. And I don't understand how I can use .env in this .js.

Let's say I have some specific environment variable, for example MY_URL and my JS file:

const myUrl = process.env.VUE_APP_MY_URL;

And it's not working, because static files from public folder don't processed by webpack as I understand.

Maybe someone knows good solution? Or maybe other solutions\workarounds?

In my case, I put .js to src and add new entry by chainWebpack:

config.entryPoints.delete('app')

config.entry('app')
    .add('./src/main.ts')
    .end()
    .entry('myScript')
    .add('./src/myScript.js')
    .end()

And now webpack build the script as separate file, but injects to index.html with app.js. This is not what I really want.

So, main purpose - build separate static JS file with specific name without hash (for example, myScript.js) which would contain variable from .env (.env.production, .env.development)

  • Can you just store two versions of the env variable? One in `.env` and one in your actual environment? in .js files use `process.env.MY_ENV` in .vue files use `process.env.VUE_APP_MY_URL;` – Jesse Reza Khorasanee Apr 23 '21 at 00:23
  • @JesseRezaKhorasanee yes, I can, but It won't work because `process` variable is not available in static JS files in `public` folder (`ReferenceError: process is not defined`). In `index.html` we can use `BASE_URL` (``). Maybe there is the same for static JS? Hopefully I don't need to write my own JS-loader for this. – Sergey Safronov Apr 23 '21 at 06:19
  • I see. Can I ask why you need environment variables in the public folder? Without node, there is not a way to access environment variables as far as I know. – Jesse Reza Khorasanee Apr 23 '21 at 06:45
  • I think this thread should give you a solution: https://forum.vuejs.org/t/environment-variables-inside-files-js-under-public-folder/40322 – Jesse Reza Khorasanee Apr 23 '21 at 06:49
  • I need env. variable in public folder because my static script contains functions and classes for iFrame (external usage by other sites). And I need to change URLs depending on environment (production, development). – Sergey Safronov Apr 23 '21 at 07:37
  • So, in file I would have `const myUrl = process.env.VUE_APP_MY_URL;` After build for production: `const myUrl ='https://www.production.com';` After build for development: `const myUrl ='https://www.development.com';` And it's not only variable for `base_url`, also I have 3rd party URLs (sandboxes for development, and production APIs for production) – Sergey Safronov Apr 23 '21 at 07:38
  • Solution in your link looks same as mine with moving script to `src` and adding new `entry`, but my script start to inject to `index.html`, because webpack decides that my script for iFrame (script for external usage) - other entry point. – Sergey Safronov Apr 23 '21 at 07:39

1 Answers1

3

Main fact about static files in public folder from docs:

Static assets placed in the public directory will simply be copied and not go through webpack

So, I cannot use .env with static files in public.

I haven't found a perfect solution, but at least 3 acceptable options:


  1. JS file as entry, as Jesse Reza Khorasanee said in comments and gave a link to almost same question

The main idea: configure vue.config.js for an additional entry and force webpack to process my file.

// vue.config.js

module.exports = {
  configureWebpack: {
    entry: {
      public: "./public/main.js"
    },
    output: {
      filename: "[name]/[name].main.js"
    }
  }
};

This solution would work with certain features:

  • at least two entry points: main entry for my SPA (main.js) and additional entry just for my static JS. It's not good, because processed JS would contain a link to vendors.js chunk as one of the entries. But I need JS file processed by webpack only.

  • same output.filename and hash in filename with clear config (it's not work, because I use this script as 3rd party JS and load by static name), or different output.filename for my JS file but with dirty config:

configureWebpack: config => {
        config.output.filename = (pathData) => {
            return pathData.chunk.name === 'myScript'
                ? '[name].js' : '[name].[hash].js';
        };
    ...
}
  • If I leave my JS in public folder I get two files after build: one in default js folder with other static assets and another in root folder near main.js

  1. Multi-Page Application (configuration for Vue multi-page mode)
module.exports = {
  pages: {
    index: {
      // entry for the page
      entry: 'src/index/main.js',
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // when using the entry-only string format,
    // template is inferred to be `public/myScript.html`
    // and falls back to `public/index.html` if not found.
    // Output filename is inferred to be `myScript.html`.
    myScript: 'src/myScript.js'
  }
}

This solution would work almost like the first solution and I get a clear config file. But still I have problem with vendors.js seems like pages option work directly with html-webpack-plugin and I can config chunks which would load with my page, and I tried different ways to setup this option but without success. Vendors is still part of myScript entry.


  1. Build JS file as library

I chose this solution in my case. Because it's clear and short.

I put additional script to my package.json: vue-cli-service build --no-clean --target lib --name paysendPaymentLibrary src/payment.js and change main build script.

Final version of package.json:

...
"scripts": {
    "build": "vue-cli-service build && npm run build-library",
    "build-library": "vue-cli-service build --no-clean --target lib --name myScriptLibrary src/myScript.js"
  },
...

After run npm run build I get static files for SPA and three files for my script:

  • myScriptLibrary.umd.min.js
  • myScriptLibrary.umd.js
  • myScriptLibrary.common.js

For 3rd party site I use myScriptLibrary.umd.js file.

If you choose this solution be careful when you build your application, because:

  • in Windows vue-cli-service build & npm run build-library scripts would run sequentially, but in Unix it runs in parallel. It can cause deletion of your SPA files. So be sure to use && instead of & (see discussions about environments and parallel\sequential script running)
  • size of processed files would be bigger than raw static JS. For example, in my case raw file size: 4 KiB, after build: 15.44 KiB, gzipped: 5.78 KiB.