简体   繁体   English

Webpack:如何在构建时转换变量

[英]Webpack : How to convert variables on build

About using Vue (vue-loader) + Webpack and Chromatism 关于使用Vue (vue-loader) + WebpackChromatism

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 ? 是否有可能告诉Webpack构建版本转换rgb(0,0,0)

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! 正如之前的答案和评论已经提到过,没有现成的AOT编译器可以处理这种情况(我的意思是这是一个非常具体的案例,没有通用工具能够处理它),没有什么可以阻止你从推出自己的加载器/插件来处理这个任务!
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. 您可以使用自定义Webpack LoaderNode的VM Module在构建时执行代码,获取其输出并将其替换为源文件中的函数调用。
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 : 然后在你的production.webpack.js (或类似的文件)中取自这个问题

// 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). 此外,整个内容可以使用webpack插件实现(只是我没有足够的知识来创建一个)。 For a quick starter refer to this wiki to learn how to create a custom plugin. 有关快速入门的信息, 请参阅此Wiki以了解如何创建自定义插件。

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. 然后,对于每个有效源,在上下文中执行source语句并获取结果。
    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. 尝试使用回调加载程序来处理所有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)); }evalDuringCompile: function(code) { return JSON.stringify(eval(code)); } evalDuringCompile: function(code) { return JSON.stringify(eval(code)); }

State of Art optimizer cannot handle arbitrary expression. State of Art优化器无法处理任意表达式。 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. prepack将在编译时评估代码并输出计算值。 However, it is not generally considered production ready. 但是,通常不认为生产准备就绪。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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