From 678a7f955cfbcc1366a5aaf11325cac122a8f7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 9 Jul 2018 12:26:29 +0200 Subject: [PATCH] Reworked browser builds, make default build compatible with both node & browsers due to non-ideal browser field support --- .babelrc.js | 1 + package.json | 2 ++ rollup.config.js | 11 ----------- src/calculateNodeHeight.js | 15 +++++++-------- src/index.js | 5 +++-- src/isBrowser.js | 1 + src/isBrowser.macro.js | 28 ++++++++++++++++++++++++++++ 7 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 src/isBrowser.js create mode 100644 src/isBrowser.macro.js diff --git a/.babelrc.js b/.babelrc.js index d83f474a..ad718774 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -12,5 +12,6 @@ module.exports = { ['@babel/proposal-class-properties', { loose }], ['@babel/proposal-object-rest-spread', { loose }], ['transform-react-remove-prop-types', { mode: 'unsafe-wrap' }], + 'macros', ] } diff --git a/package.json b/package.json index 1825d9a0..a56a78de 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,12 @@ }, "devDependencies": { "@babel/core": "7.0.0-beta.51", + "@babel/helper-module-imports": "7.0.0-beta.52", "@babel/plugin-proposal-class-properties": "7.0.0-beta.51", "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.51", "@babel/preset-env": "7.0.0-beta.51", "@babel/preset-react": "7.0.0-beta.51", + "babel-plugin-macros": "^2.2.2", "babel-plugin-transform-define": "^1.3.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.13", "cross-env": "^5.0.1", diff --git a/rollup.config.js b/rollup.config.js index d6438ba5..a995dd79 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -21,20 +21,11 @@ const makeExternalPredicate = externalArr => { const createConfig = ({ output, browser = true, - server = false, umd = false, env, } = {}) => { const min = env === 'production'; - if (browser && server) { - throw new Error('Bundle cannot target both `browser` & `server` at the same time. Pass `true` only to one of these options.'); - } - - if (!browser && !server) { - throw new Error('Bundle must target `browser` or `server` environment. Pass `true` to one of these options.'); - } - return { input: 'src/index.js', output: ensureArray(output).map(format => Object.assign( @@ -62,7 +53,6 @@ const createConfig = ({ : {}, { 'process.env.BROWSER': JSON.stringify(browser), - 'process.env.SERVER': JSON.stringify(server), } )), min && uglify({ @@ -90,7 +80,6 @@ export default [ { file: pkg.main, format: 'cjs' }, { file: pkg.module, format: 'esm' }, ], - server: true, browser: false, }), createConfig({ diff --git a/src/calculateNodeHeight.js b/src/calculateNodeHeight.js index 4bd641c0..255613a5 100644 --- a/src/calculateNodeHeight.js +++ b/src/calculateNodeHeight.js @@ -1,6 +1,6 @@ -const isIE = process.env.BROWSER - ? !!document.documentElement.currentStyle - : false; +import isBrowser from './isBrowser.macro'; + +const isIE = isBrowser ? !!document.documentElement.currentStyle : false; const HIDDEN_TEXTAREA_STYLE = { 'min-height': '0', @@ -38,8 +38,7 @@ const SIZING_STYLE = [ ]; let computedStyleCache = {}; -const hiddenTextarea = - process.env.BROWSER && document.createElement('textarea'); +const hiddenTextarea = isBrowser && document.createElement('textarea'); const forceHiddenStyles = node => { Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(key => { @@ -47,7 +46,7 @@ const forceHiddenStyles = node => { }); }; -if (process.env.BROWSER) { +if (isBrowser) { forceHiddenStyles(hiddenTextarea); } @@ -96,11 +95,11 @@ export default function calculateNodeHeight( // measure height of a textarea with a single row hiddenTextarea.value = 'x'; const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; - + // Stores the value's rows count rendered in `hiddenTextarea`, // regardless if `maxRows` or `minRows` props are passed const valueRowCount = Math.floor(height / singleRowHeight); - + if (minRows !== null) { minHeight = singleRowHeight * minRows; if (boxSizing === 'border-box') { diff --git a/src/index.js b/src/index.js index 14f443ea..ed8d270d 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import calculateNodeHeight, { purgeCache } from './calculateNodeHeight'; +import isBrowser from './isBrowser.macro'; const noop = () => {}; @@ -12,7 +13,7 @@ const noop = () => {}; // eval('"use strict"; var onNextFrame = window.cancelAnimationFrame; onNextFrame(4);') // so we bind window as context in dev modes const [onNextFrame, clearNextFrameAction] = - process.env.BROWSER && window.requestAnimationFrame + isBrowser && window.requestAnimationFrame ? process.env.NODE_ENV !== 'development' ? [window.requestAnimationFrame, window.cancelAnimationFrame] : [ @@ -128,7 +129,7 @@ export default class TextareaAutosize extends React.Component { }; _resizeComponent = (callback = noop) => { - if (!process.env.BROWSER) { + if (!process.env.BROWSER && !this._ref) { callback(); return; } diff --git a/src/isBrowser.js b/src/isBrowser.js new file mode 100644 index 00000000..a9a0e8a2 --- /dev/null +++ b/src/isBrowser.js @@ -0,0 +1 @@ +export default typeof window !== 'undefined' && typeof document !== 'undefined'; diff --git a/src/isBrowser.macro.js b/src/isBrowser.macro.js new file mode 100644 index 00000000..ca9e5332 --- /dev/null +++ b/src/isBrowser.macro.js @@ -0,0 +1,28 @@ +const { createMacro, MacroError } = require('babel-plugin-macros'); +const { addDefault } = require('@babel/helper-module-imports'); + +module.exports = createMacro(({ references, babel: { template } }) => { + const usedReferences = Object.keys(references); + + if (usedReferences.length > 1 || usedReferences[0] !== 'default') { + throw new MacroError( + `${__filename} must be used as default import, instead you have used it as: ${usedReferences.join( + ', ', + )}.`, + ); + } + + const { name: insertedName } = addDefault( + references.default[0], + './isBrowser', + { nameHint: 'isBrowser' }, + ); + + const enhancedIsBrowser = template(`process.env.BROWSER || ${insertedName}`, { + placeholderPattern: false, + }); + + references.default.forEach(isBrowser => { + isBrowser.replaceWith(enhancedIsBrowser().expression); + }); +});