首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于ES6的条件导出process.env.NODE_ENV模块的可能性?

基于ES6的条件导出process.env.NODE_ENV模块的可能性?
EN

Stack Overflow用户
提问于 2019-03-19 21:18:14
回答 3查看 3.1K关注 0票数 7

我编写了一个实用程序库,当我的用户publishes他们的应用程序时,我想对它们进行publishes

在Webpack v4中,您需要使模块ES6支持tree-shaking,但我也希望将development buildproduction build拆分为不同的文件。

我想要的正是react的NPM模块:

代码语言:javascript
复制
// index.js
'use strict';

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react.production.min.js');
} else {
  module.exports = require('./cjs/react.development.js');
}

这给我带来了问题。

如果我让我的实用模块都是commonjs,我就永远得不到tree-shaking,我的应用程序变得如此庞大。

如果我将我的实用模块全部设置为ES6 static export,则必须在production code中包括development message

发布两个模块(例如:my-utilitymy-utility-es)不会有帮助,因为在开发过程中,我的代码如下所示:

代码语言:javascript
复制
import { someFunc } from 'my-utility';

但是在生产代码中,我必须将其更改为:

代码语言:javascript
复制
import { someFunc } from 'my-utility-es';

我该如何解决这个问题?

更新

更清楚的是,我的development buildproduction build包含不同的源代码(例如:产品构建删除了所有错误消息)

所以说webpack的模式对我来说并不令人满意。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-27 09:46:12

我自己找到了答案,我认为最好的方法就是通过babel macros

代码语言:javascript
复制
import { something } from 'myLibrary/macro';

// In webpack development:
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
// import { something } from 'myLibrary/development';

// In webpack production:
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
// import { something } from 'myLibrary/production';

我的宏实现:

代码语言:javascript
复制
import { createMacro } from 'babel-plugin-macros';

function macro({ references, state, babel }) {
  state.file.path.node.body.forEach(node => {
    if (node.type === 'ImportDeclaration') {
      if (node.source.value.includes('myLibrary/macro')) {
        if (process.env.NODE_ENV === 'production') {
          node.source.value = 'myLibrary/module/production';
        } else {
          node.source.value = 'myLibrary/module/development';
        }
      }
    }
  });

  return { keepImports: true };
}

export default createMacro(macro);
票数 2
EN

Stack Overflow用户

发布于 2020-04-05 11:19:01

这里是我找到的最好的解决方案,不需要用户使用Babel宏.

让我们说:

  • 我们的图书馆叫crazy-components
  • 它导出两个名为ComponentAComponentB的反应组件。
  • 组件仅使用代码围栏在dev模式下进行某些日志记录。
代码语言:javascript
复制
// src/index.js
import React from 'react';

export function ComponentA(props) {
  if (process.env.NODE_ENV !== 'production') {
    console.log(`Rendering ComponentA with props ${props}`);
  }

  return <div>ComponentA message: {props.msg}</div>;
}

export function ComponentB(props) {
  if (process.env.NODE_ENV !== 'production') {
    console.log(`Rendering ComponentB with props ${props}`);
  }

  return <div>ComponentB message: {props.msg}</div>;
}

我们希望图书馆:

  1. 如果用户使用import { ComponentA } from 'crazy-components',那么ComponentB的代码就不会在它们的包中结束。
  2. 日志代码将从生产包中剥离。

解决方案

1.带汇总的包库

2.配置汇总,以便在生产版本和dev版本中创建CJS和ESM版本(生产版本中删除了日志代码等)。

CJS构建输出到/dist/cjs,ESM生成输出到/dist/esm。文件被称为crazy-components.prod.min.jscrazy-components.dev.js

只有dev构建包含日志代码(没有解释如何进行所有这些工作,如果您正在阅读这些代码,您可能已经知道了)。

3.为CJS和ESM建立以下切入点:

代码语言:javascript
复制
// index.js
if (process.env.NODE_ENV === 'production') {
    module.exports = require('./dist/cjs/crazy-components.min.js');
} else {
    module.exports = require('./dist/cjs/crazy-components.js');
}
代码语言:javascript
复制
// es/index.js
import {
    ComponentA as ComponentA_prod,
    ComponentB as ComponentA_prod
} from '../dist/esm/crazy-components.prod.min.js';

import {
    ComponentA as ComponentA_dev,
    ComponentB as ComponentA_dev
} from '../dist/esm/crazy-components.dev.js';

export const ComponentA = process.env.NODE_ENV === 'production' ? ComponentA_prod : ComponentA_dev;
export const ComponentB = process.env.NODE_ENV === 'production' ? ComponentB_prod : ComponentB_dev;

4.指向package.json中的两个入口点

代码语言:javascript
复制
// package.json
{
  "name": "crazy-components",
  "version": "1.0.0",
  "main": "index.js",
  "module": "es/index.js",
  "sideEffects": false
}

5. (可选)使NodeJS中作为ESM的重要性

节点12 (带标志)和节点13+ 本地支持ES模块

添加到package.json

代码语言:javascript
复制
  "exports": {
    ".": {
      "import": "./es/index.js",
      "require": "./index.js"
    },
    "./es": "./es/index.js"
  },

package.json文件夹中添加额外的es文件,将文件夹的内容标记为NodeJS:

代码语言:javascript
复制
// es/package.json
{
  "type": "module"
}

使用汇总-插件-复制获取汇总,也可以将该文件复制到dist/esm

代码语言:javascript
复制
// rollup.config.js
import copy from 'rollup-plugin-copy';
/* ... other imports ... */

export default {
  input: 'src/index.js',
  /* ... other config ... */
  plugins: [
    /* ... other plugins ... */
    copy({targets: [{src: 'es/package.json', dest: 'dist/esm'}]})
  ]
};

可能的改进

es/index.js是手工创建的,因此如果稍后添加ComponentC,则还需要将其添加到es/index.js中。如果有一个自动创建es/index.js的Rollup插件是理想的,但我还没有找到一个。

此外,您的里程可能会有所不同。我今天才刚试过这个。当这个库被导入到一个创建反应-应用程序应用程序中时,它似乎像你所期望的那样工作,但是我还没有用手编码的Webpack吐露来测试它。

这种方法应该可以推广到任何库,而不仅仅是响应组件,而且我还没有尝试过。

任何关于改进的建议都非常欢迎!

票数 1
EN

Stack Overflow用户

发布于 2019-03-26 08:23:50

解决这个问题所需要的就是使用mode。见指定模式

自webpack v4以来,指定模式将自动为您配置DefinePlugin:

webpack.prod.js

代码语言:javascript
复制
  const merge = require('webpack-merge');
  const common = require('./webpack.common.js');

  module.exports = merge(common, {
    mode: 'production',
  });

他们提到了React的名字:

如果您使用的是react之类的库,那么在添加这个插件之后,您实际上应该会看到包的大小有了明显的下降。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55250139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档