afterwind-io / preprocessor-loader

Bring the awesome "Conditional Compilation" to the Webpack, and more.
MIT License
40 stars 12 forks source link

vue cli3 怎么配置json格式 #15

Closed zhangchenna closed 3 years ago

afterwind-io commented 3 years ago

@zhangchenna 之前设计这个loader的时候没有考虑过其他cli工具的情况,但只要第三方的内核是webpack就能跑(理论上)。

我看了下vue cli的文档,它是支持修改内部webpack配置的: https://cli.vuejs.org/guide/webpack.html#adding-a-new-loader https://github.com/neutrinojs/webpack-chain#config-module-rules-uses-loaders-creating

所以假如你要在js/ts代码里面使用预编译,你可以:

  1. 先正常在代码里写预编译逻辑:
    
    <script>
    import HelloWorld from "./components/HelloWorld.vue";

export default { name: "App", components: { HelloWorld, }, computed: { title: () => { // #!if !foo return "FOO"; // #!else return "BAR"; // eslint-disable-line no-unreachable // #!endif }, }, };


2. 在`vue.config.js`当中加入以下这段:
```javascript
module.exports = {
  chainWebpack: (config) => {
    const jsRule = config.module.rule('js');
    jsRule
      .use('webpack-preprocessor-loader')
      .loader('webpack-preprocessor-loader')
      .options({
        params: {
          foo: true,
        },
      });
  },
};
zhangchenna commented 3 years ago

目前就是这么配置,js下生效json下不生效,其他类似库是可以的

afterwind-io commented 3 years ago

无论是vue cli还是webpack的配置都需要指定处理文件的类型。针对js文件的规则不会应用到JSON文件的处理逻辑上。

另外,标准的JSON不支持注释,你需要使用JSON5,同时把加注注释的文件名后缀改成".json5"方便区分。

综上所述,针对JSON部分的大致配置如下:

module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('json5')
      .test(/\.json5$/)
      .use('json5-loader')
      .loader('json5-loader')
      .end()
      .use('webpack-preprocessor-loader')
      .loader('webpack-preprocessor-loader')
      .options({
        params: {
          foo: true,
        },
      });
  },
};
afterwind-io commented 3 years ago

webpack-preprocessor-loader本来就可以处理JSON,因为本质上是针对纯文本做处理,与文件格式无关。首先你需要给JSON文件添加自定义loader。然后在代码里你只要正常导入,JSON里面正常写预编译条件就行了。

config.module
      .rule('json')
      .test(/\.json$/)
      .use('webpack-preprocessor-loader')
      .loader('webpack-preprocessor-loader')
      .options({
        params: {
          foo: false,
        },
      });
// myFile.json
{
  // #!if foo
  "value": "1"
  // #!else
  "value": "2"
  // #!endif
}
<script>
import myObject from "./myFile.json";

// ...
</script>

之所以建议使用JSON5格式是因为:

  1. 标准的JSON规范不支持注释,在JSON文件里面直接写注释,你的编辑器/IDE可能会报错,但是经过预编译后的打包是没有问题的

  2. 直接使用JSON做预编译,你的编辑器/IDE可能还会报缺少","的问题,甚至可能会出错。

以上面给的myFile.json为例,假如你在"value": "1"后面加了,,并且条件footrue,那么编译结果出来的内容就是

{
  "value": "1",
}

这个不是合法的JSON,因为多了个,。这样输出的JSON因为包含语法错误,是没法正常打包的。

为了保证编译结果正确,就必须像之前的例子一样,一律不加,,但编辑器可能就会报错。如果你选择无视编辑器错误,那也没问题。

然而,JSON5是支持Trailing Comma的,所以你可以在JSON5文件里面直接都加上,,这样编辑器也不会报错,编译结果也不会有问题:

// myFile.json
{
  // #!if foo
  "value": "1",
  // #!else
  "value": "2", // <- 注意这个 ","
  // #!endif
}
  1. 使用.json5后缀显式声明了这个文件不是标准的JSON,因为包含了规范不支持的内容(注释)。

如果你之前没有了解过JSON5,可以参考下面的规范链接,或者直接百度: https://json5.org/