Webpack.DefinePlugin equivalent

Is there an equivalent to DefinePlugin to statically replace variables at build-time before the minifier?
This is necessary to handle feature flags in Vue 3. Thanks!

1 Like

Tried something like this without success:

import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions'
import { VueCompiler } from './compiler'
import BabelPluginSearchAndReplace from 'babel-plugin-search-and-replace'

checkNpmVersions({
  vue: '^3.1.0',
  '@vue/compiler-sfc': '^3.1.0',
}, 'vuejs:vue3')

// Add babel plugins
const getBabelDefaults = Babel.getDefaultOptions
Babel.getDefaultOptions = (features) => {
  const config = getBabelDefaults(features)
  if (!config.plugins) {
    config.plugins = []
  }
  config.plugins.push([BabelPluginSearchAndReplace, {
    rules: [
      {
        search: '__VUE_OPTIONS_API__',
        replace: process.env.__VUE_OPTIONS_API__ || 'true',
      },
      {
        search: '__VUE_PROD_DEVTOOLS__',
        replace: process.env.__VUE_PROD_DEVTOOLS__ || 'false',
      },
      {
        search: 'process.env.NODE_ENV',
        replace: JSON.stringify(process.env.NODE_ENV || 'development'),
      },
    ],
  }])
  return config
}

Plugin.registerCompiler({
  extensions: ['vue'],
  filenames: ['.vueignore'],
}, () => new VueCompiler())
1 Like

@akryum I’m pretty sure Meteor handles all of this with Babel via a .babelrc file in the root directory of the project. Meteor has a default .babelrc file (see link to GitHub repo).

I have a .babelrc file in my root project directory that I was configuring to handling production vs. development, but had not done anything with it yet. Here are the contents:

{
    "env": {
        "development": {
            "plugins": [

            ]
        },
        "production": {
            "plugins": [

            ]
        }
    }
}

Also here is a comment by @benjamn from here where he stated that Meteor did not support babel.config.js yet.

Taking a look at how to use babel-plugin-search-and-replace from the npm docs we get the following example on how too specify the rules in the .babelrc file:

// Add the following lines in your .babelrc

{
  "plugins": [
    [
      "search-and-replace",
      {
        "rules": [
          {
            "search": "searchedString",
            "searchTemplateStrings": true,
            "replace": "replacement"
          },
          {
            "search": /myRegex/,
            "replace": "replacement"
          }
        ]
      }
    ]
  ]
}

It’s worth noting that the Meteor Github repos shows how to configure this via the Node API, which might be better than the .babelrc file for a Vue 3 integration.

require("babel-core").transform("code", {
  presets: ["meteor"],
  plugins: [
    [
      "search-and-replace",
      {
        rules: [
          {
            search: '__VUE_OPTIONS_API__',
            replace: process.env.__VUE_OPTIONS_API__ || 'true',
          },
          {
             search: '__VUE_PROD_DEVTOOLS__',
             replace: process.env.__VUE_PROD_DEVTOOLS__ || 'false',
           },
           {
              search: 'process.env.NODE_ENV',
              replace: JSON.stringify(process.env.NODE_ENV || 'development'),
           },
        ]
      }
    ]
  ]
});

It looks like @storyteller was the last on to contribute to updates on Meteor’s default .babelrc contents, so maybe he could confirm the above approach. From a quick search in the forum, @coagmano also has some background on this topic.

@storyteller , @coagmano , or @filipenevola… if you could provide any extra details here, it would be greatly appreciated! @filipenevola it would be really cool to get some support from your internal core team on this too if that’s possible :slight_smile:

1 Like

It would be nice to have a define feature at the isobuild level since babel isn’t exactly fast.

1 Like

Isn’t the simplest solution is to put this in any of your client js files, like /client/main.js ?

if (Meteor.isDevelopment) {
  global.__VUE_OPTIONS_API__ = true
  global.__VUE_PROD_DEVTOOLS__ = true
  global.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = true
} else {
  global.__VUE_OPTIONS_API__ = false
  global.__VUE_PROD_DEVTOOLS__ = false
  global.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false
}