我编写了一个实用程序库,当我的用户publishes他们的应用程序时,我想对它们进行publishes。
在Webpack v4中,您需要使模块ES6支持tree-shaking,但我也希望将development build和production build拆分为不同的文件。
我想要的正是react的NPM模块:
// 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-utility和my-utility-es)不会有帮助,因为在开发过程中,我的代码如下所示:
import { someFunc } from 'my-utility';但是在生产代码中,我必须将其更改为:
import { someFunc } from 'my-utility-es';我该如何解决这个问题?
更新
更清楚的是,我的development build和production build包含不同的源代码(例如:产品构建删除了所有错误消息)。
所以说webpack的模式对我来说并不令人满意。
发布于 2019-03-27 09:46:12
我自己找到了答案,我认为最好的方法就是通过babel macros
import { something } from 'myLibrary/macro';
// In webpack development:
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
// import { something } from 'myLibrary/development';
// In webpack production:
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
// import { something } from 'myLibrary/production';我的宏实现:
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);发布于 2020-04-05 11:19:01
这里是我找到的最好的解决方案,不需要用户使用Babel宏.
让我们说:
crazy-componentsComponentA和ComponentB的反应组件。// 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>;
}我们希望图书馆:
import { ComponentA } from 'crazy-components',那么ComponentB的代码就不会在它们的包中结束。解决方案
1.带汇总的包库
2.配置汇总,以便在生产版本和dev版本中创建CJS和ESM版本(生产版本中删除了日志代码等)。
CJS构建输出到/dist/cjs,ESM生成输出到/dist/esm。文件被称为crazy-components.prod.min.js和crazy-components.dev.js。
只有dev构建包含日志代码(没有解释如何进行所有这些工作,如果您正在阅读这些代码,您可能已经知道了)。
3.为CJS和ESM建立以下切入点:
// 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');
}// 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中的两个入口点
// 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中
"exports": {
".": {
"import": "./es/index.js",
"require": "./index.js"
},
"./es": "./es/index.js"
},在package.json文件夹中添加额外的es文件,将文件夹的内容标记为NodeJS:
// es/package.json
{
"type": "module"
}使用汇总-插件-复制获取汇总,也可以将该文件复制到dist/esm中
// 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吐露来测试它。
这种方法应该可以推广到任何库,而不仅仅是响应组件,而且我还没有尝试过。
任何关于改进的建议都非常欢迎!
发布于 2019-03-26 08:23:50
https://stackoverflow.com/questions/55250139
复制相似问题