1

I'm trying to create a custom html element with vuejs and vite. But every time I build the element, process.env.NODE_ENV is added to the js and so using the component outside of vuejs fails. My goal is an element I can use in any generic html file. I've done this before with stenciljs, but not with vuejs and I can't figure out what I'm doing wrong. I have no reference to env in my vue file.

My build command: "build:simple": "vite build --config ./src/components/simple/vite.simple.config.ts"

vite.simple.config.ts:

import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';

const componentName = 'simple';

const entry = `src/components/${componentName}/index.ts`;
const fileName = `${componentName}`;
const outDir = `./dist/${componentName}`;
const name = `${componentName}`;

export default defineConfig({
  plugins: [
    vue( {customElement: true} ),
  ],
  logLevel: 'info',
  build: {
    outDir: outDir,
    lib: {
      entry: entry,
      name: name,
      fileName: fileName
    },
  },
});

My index.ts file:

import { defineCustomElement } from 'vue';
import Simple from "./Simple.vue";

const SimpleElement = defineCustomElement(Simple);

function loader() {
  const ceRegistry = window.customElements
  if ( ceRegistry === null) {
    return;
  } else {
    if ( typeof(ceRegistry.get('my-simple') ) === 'undefined') {
      ceRegistry.define('my-simple', SimpleElement);
    }
    return;
  }
}

const ceRegistry = window.customElements;
if ( ceRegistry !== null) {
  if ( typeof(ceRegistry.get('my-simple') ) === 'undefined') {
    ceRegistry.define('my-simple', SimpleElement);
  }
}


declare module 'vue' {
  export interface GlobalComponents {
    'SimpleElement': typeof SimpleElement
  }
}

export { Simple, SimpleElement, loader }

The only thing at all complicated I'm doing is setting the paths to the various files based on a variable, which I'm doing because I want to re-use the config for different components and then just change the componentName variable each time. Based on https://vuejs.org/guide/extras/web-components, this should do it. But I've got over 100 instances of process.env.NODE_ENV in my js, so it is constantly failing.

I'm using vue 3.3.4, vitejs/plugin-vue 4.4.0, and vite 5.0.10.

Any ideas?

Edit for clarification: The code is sort of duplicated because I wasn't sure if I would need to import the loader function and run it in the consuming html. When I create a custom html element with stencil, I can import the loader function into an angular app and run it to register the component. So I just wasn't sure if I should do all of the registration in the index.ts or create a function and export it.

Here are two examples of the code from simple.js (188 references to process.env.NODE_ENV total):

const K = process.env.NODE_ENV !== "production" ? Object.freeze({}) : {},
ht = process.env.NODE_ENV !== "production" ? Object.freeze([]) : []

And 2 from simple.umd.js (188 references to process.env.NODE_ENV total):

const L=process.env.NODE_ENV!=="production"?Object.freeze({}):{},
ct=process.env.NODE_ENV!=="production"?Object.freeze([]):[]

I took my index.ts file down to just this and I still have 51 references in each of the js files:

import { defineCustomElement } from 'vue';
import Simple from "./Simple.vue";

const SimpleElement = defineCustomElement(Simple);
3
  • "But I've got over 100 instances of process.env.NODE_ENV" - it's unclear what you mean. NODE_ENV isn't used in the code you posted. Generally process.env.NODE_ENV is supposed to be interpolated on build, so there shouldn't be such problem even if you explicitly used NODE_ENV Commented Dec 19, 2023 at 18:03
  • Why do you do two times the same thing? The contents of the loader function include the same code as the loader function. You could just call the loader function below... And how can you have instances of process.env.NODE_ENV in your code? Can you clarify a bit more? Commented Dec 19, 2023 at 19:06
  • 'Generally process.env.NODE_ENV is supposed to be interpolated on build, so there shouldn't be such problem even if you explicitly used NODE_ENV' except that because the js is being used in plain old html, process is null, so trying to access process.env.NODE_ENV throws an error trying to access a null object. And the references to process.env.NODE_ENV only exist after a vite build, so something in the build step is inserting them. Commented Dec 19, 2023 at 19:35

1 Answer 1

1

Nothing helps you find the answer to a question like asking someone else.

@Estus Flask was so close. Finally saw the note on https://vitejs.dev/guide/build#library-mode.

In library mode, all import.meta.env.* usage are statically replaced when
building for production. However, process.env.* usage are not, so that 
consumers of your library can dynamically change it. If this is undesirable,
you can use define: { 'process.env.NODE_ENV': '"production"' } for example to 
statically replace them, or use esm-env for better compatibility with bundlers 
and runtimes.

So while all of the import.meta.env variables were replaced as part of npm build, the process.env.NODE_ENV is specifically not replaced. I defined it and that seems to have removed that reference. I may still have other errors, but the references to process.env.NODE_ENV are gone.

N.B. the note for this is on the library page, so you would think it would go lib section. Nope. And since it is specifically related to building, you might think it would go in the build section. Nope. It goes in the root of the definConfig object:

export default defineConfig({
  define: { 'process.env.NODE_ENV': '"production"' },
  build: {
    lib: {
    }
  }
});
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.