简体   繁体   中英

Webpack : How to convert variables on build

About using Vue (vue-loader) + Webpack and Chromatism

Example: (on dev / source)

let textColor = chromatism.contrastRatio('#ffea00').cssrgb // => rgb(0,0,0)

Does it possible to tell Webpack to convert to rgb(0,0,0) on build version ?

So on build version should be converted something like: (for performance )

let textColor = 'rgb(0,0,0)'

As previous answers and comments have already mentioned that there are no readily available AOT compilers to handle this kind of a situation (I mean this is a very specific case and no general purpose tool could be able to handle it), there is nothing stopping you from rolling out your own loader/plugin to handle this task!
You can use a custom Webpack Loader and Node's VM Module to execute the code at buildtime, get its output and replace it with the function call in your source file.
A sample implementation of this idea can look like the following snippet:

// file: chromatismOptimizer.js

// node's vm module https://nodejs.org/api/vm.html
const vm = require('vm')

const chromatism = require('chromatism')

// a basic and largley incomplete regex to extract lines where chromatism is called
let regex = /^(.*)(chromatism\S*)(.*)$/

// create a Sandbox 
//https://nodejs.org/api/vm.html#vm_what_does_it_mean_to_contextify_an_object
// this is roughly equivalent to the global the context the script will execute in
let sandbox = {
  chromatism: chromatism
}

// now create an execution context for the script
let context = new vm.createContext(sandbox)

// export a webpack sync loader function
module.exports = function chromatismOptimizer(source){
  let compiled = source.split('\n').reduce((agg, line) => {
    let parsed = line.replace(regex, (ig, x, source, z) => {
      // parse and execute the script inside the context
      // return value is the result of execution
      // https://nodejs.org/api/vm.html#vm_script_runincontext_contextifiedsandbox_options
      let res = (new (vm.Script)(source)).runInContext(context)
      return `${x}'${res}'${z? z : ''}`
    })
    agg.push(parsed)
    return agg;
  }, []).join('\n');

  return compiled;
}

Then in your production.webpack.js (or somefile like that) taken from this issue :

// Webpack config
resolveLoader: {
  alias: {
    'chromatism-optimizer': path.join(__dirname, './scripts/chromatism-optimizer'),
  },
}
// In module.rules
{
  test: /\.js$/,
  use: ['chromatism-optimizer'],
}

NOTE: This is just a reference implementation and is largely incomplete. The regex used here is quite basic and may not cover many other use cases, so make sure you update the regex. Also this whole stuff can be implemented using webpack plugins (it's just that I don't have sufficient knowledge of how to create one). For a quick starter refer to this wiki to learn how to create a custom plugin.

The basic idea is simple.

  1. First create a sandboxed environment,
    let sandbox = { chromatism:chromatism, ...}

  2. Then create an execution context,
    let context = new vm.createContext(sandbox)

  3. Then for each valid source, execute the source statement in the context and get the result.
    let result = (new (vm.Source)(source)).runInContext(context)

  4. Then maybe replace the original source statement with the result.

Try using call-back loader to process all your JavaScript. Define a callback function for this specific case or even something more general like: evalDuringCompile: function(code) { return JSON.stringify(eval(code)); } evalDuringCompile: function(code) { return JSON.stringify(eval(code)); }

State of Art optimizer cannot handle arbitrary expression. In this case, the most reliable solution is hard code constant in your code like this.

let textColor = process.env.NODE_ENV === 'production' ? 'rgb(0,0,0)' :  chromatism.contrastRatio('#ffea00').cssrgb;

Some futuristic optimizer does handle situation like this. prepack will evaluate code at compile time and output computed values. However, it is not generally considered production ready.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM