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)

7
  • 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; Commented Apr 23, 2021 at 0: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 (<link rel="icon" href="<%= BASE_URL %>favicon.ico">). Maybe there is the same for static JS? Hopefully I don't need to write my own JS-loader for this. Commented Apr 23, 2021 at 6: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. Commented Apr 23, 2021 at 6:45
  • I think this thread should give you a solution: forum.vuejs.org/t/… Commented Apr 23, 2021 at 6: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). Commented Apr 23, 2021 at 7:37

1 Answer 1

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.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.