Я пытаюсь изучить webpack 4 лучше и экспериментирую с встряхиванием дерева в частной библиотеке. У меня довольно минимальный конфиг
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin
const CleanWebpackPlugin = require('clean-webpack-plugin')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const path = require('path')
const argv = require('yargs').argv
let pkg = argv.pkg || 'forms'
module.exports = {
entry: `./src/${pkg}`,
output: {
path: path.resolve(__dirname, './dist')
},
mode: 'production',
node: {
global: false,
process: false,
__filename: false,
__dirname: false,
Buffer: false,
setImmediate: false
},
plugins: [
new CleanWebpackPlugin([path.resolve(__dirname, './dist')]),
new BundleAnalyzerPlugin({
openAnalyzer: false
})
],
optimization: {
minimizer: [
new UglifyJSPlugin({
uglifyOptions: {
compress: {
sequences: false,
properties: false,
conditionals: false,
comparisons: false,
evaluate: false,
booleans: false,
loops: false,
hoist_funs: false,
hoist_vars: false,
if_return: false,
join_vars: false,
keep_fnames: true,
keep_classnames: true
},
output: { beautify: true },
mangle: false
}
})
]
}
}
У меня есть единственный файл src, который выглядит так.
// prettier-ignore
import { BareInput } from '@entrata/forms'
console.info(BareInput)
Я упростил свою библиотеку, чтобы экспортировать только два компонента (BareInput, BareEmailInput), и, как вы можете видеть, я импортирую только один из них в этом тестовом приложении webpack. Кажется, здесь должно работать встряхивание дерева, но я все еще вижу BareEmailInput в моем пакете.
Пакет моей библиотеки:
import 'date-fns/format';
import isEmail from 'validator/lib/isEmail';
import 'validator/lib/isURL';
import 'date-fns/add_minutes';
import 'date-fns/is_past';
import 'date-fns/get_year';
import 'date-fns/get_days_in_month';
import 'date-fns/is_after';
import 'date-fns/is_before';
import React from 'react';
import PropTypes from 'prop-types';
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var REQUIRED = 'This field is required';
var required = function required(_ref) {
var value = _ref.value,
required = _ref.required;
if (required && !value) {
return REQUIRED;
} else {
return '';
}
};
var email = function email(_ref3) {
var required = _ref3.required,
_ref3$value = _ref3.value,
value = _ref3$value === undefined ? '' : _ref3$value;
var trimmed = value.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+|\s$/g, '');
return trimmed ? isEmail(trimmed) ? '' : 'Please enter a valid email' : required ? REQUIRED : '';
};
/** A primitive input component. */
var BareInput = React.forwardRef(function (_ref, ref) {
var active = _ref.active,
invalid = _ref.invalid,
rest = objectWithoutProperties(_ref, ['active', 'invalid']);
return (// eslint-disable-line
React.createElement('input', _extends({ ref: ref, 'aria-invalid': invalid }, rest))
);
});
BareInput.validate = required;
BareInput.propTypes = {
/** Disables the input. */
disabled: PropTypes.bool,
/** A unique identifier for the input. */
id: PropTypes.string,
/** `true` if the input is in error state and has been touched. */
invalid: PropTypes.bool,
/** A name for the component. */
name: PropTypes.string,
/** Handler for blur event */
onBlur: PropTypes.func,
/** handler for change event */
onChange: PropTypes.func,
/** handler for focus event */
onFocus: PropTypes.func,
/** Input placeholder. */
placeholder: PropTypes.string,
/** If the input is required. Used for validation. */
required: PropTypes.bool,
/** The input type. */
type: PropTypes.string,
/** The value of the input. */
value: PropTypes.string
};
BareInput.defaultProps = {
type: 'text',
value: ''
};
/** A primitive input with email validation. */
var BareEmailInput = function BareEmailInput(props) {
return React.createElement(BareInput, props);
};
BareEmailInput.validate = email;
BareEmailInput.propTypes = {
/** Add class to input. */
className: PropTypes.string,
/** Disable the Input. */
disabled: PropTypes.bool,
/** Required Id for input. */
id: PropTypes.string.isRequired,
/** `true` when the input is in error state and has been touched. */
invalid: PropTypes.string,
/** Name for input. */
name: PropTypes.string.isRequired,
/** Handler for blur event. */
onBlur: PropTypes.func.isRequired,
/** handler for change event. */
onChange: PropTypes.func.isRequired,
/** handler for focus event. */
onFocus: PropTypes.func.isRequired,
/** Input Placeholder. */
placeholder: PropTypes.string,
/** Is the input required? */
required: PropTypes.bool,
/** Input value. */
value: PropTypes.string.isRequired
};
BareEmailInput.defaultProps = {
value: ''
};
export { BareInput, BareEmailInput };
//# sourceMappingURL=forms.es.js.map
И мой сгенерированный пакет веб-пакетов:
!function(modules) {
// React and webpack stuff removed for brevity...
var REQUIRED = "This field is required";
var BareInput = react_default.a.forwardRef(function(_ref, ref) {
_ref.active;
var invalid = _ref.invalid, rest = function(obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}(_ref, [ "active", "invalid" ]);
return react_default.a.createElement("input", _extends({
ref: ref,
"aria-invalid": invalid
}, rest));
});
BareInput.validate = function required(_ref) {
var value = _ref.value, required = _ref.required;
if (required && !value) return REQUIRED; else return "";
};
BareInput.propTypes = {
disabled: prop_types_default.a.bool,
id: prop_types_default.a.string,
invalid: prop_types_default.a.bool,
name: prop_types_default.a.string,
onBlur: prop_types_default.a.func,
onChange: prop_types_default.a.func,
onFocus: prop_types_default.a.func,
placeholder: prop_types_default.a.string,
required: prop_types_default.a.bool,
type: prop_types_default.a.string,
value: prop_types_default.a.string
};
BareInput.defaultProps = {
type: "text",
value: ""
};
var forms_es_BareEmailInput = function BareEmailInput(props) {
return react_default.a.createElement(BareInput, props);
};
forms_es_BareEmailInput.validate = function email(_ref3) {
var required = _ref3.required, _ref3$value = _ref3.value;
var trimmed = (void 0 === _ref3$value ? "" : _ref3$value).replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+|\s$/g, "");
return trimmed ? isEmail_default()(trimmed) ? "" : "Please enter a valid email" : required ? REQUIRED : "";
};
forms_es_BareEmailInput.propTypes = {
className: prop_types_default.a.string,
disabled: prop_types_default.a.bool,
id: prop_types_default.a.string.isRequired,
invalid: prop_types_default.a.string,
name: prop_types_default.a.string.isRequired,
onBlur: prop_types_default.a.func.isRequired,
onChange: prop_types_default.a.func.isRequired,
onFocus: prop_types_default.a.func.isRequired,
placeholder: prop_types_default.a.string,
required: prop_types_default.a.bool,
value: prop_types_default.a.string.isRequired
};
forms_es_BareEmailInput.defaultProps = {
value: ""
};
console.info(BareInput);
} ]);
Итак, у меня есть несколько вопросов, почему BareEmailInput все еще существует в моем пакете webpack? и почему кажется, что он обрабатывается иначе, чем BareInput? (например: почему forms_es_BareEmailInput, а не просто BareEmailInput?)
Я искал побочные эффекты, но не вижу их, и у меня есть sideEffects: false
в моем package.json для моей библиотеки.
Использование webpack v4.16.5
@ PlayMa256 Он находится в рабочем режиме. Я приукрашиваю, а не искажаю вывод, как показано в моей конфигурации webpack. Я делаю это, чтобы мне было легче анализировать вывод. Если я удалю эти настройки, он определенно уменьшит / уродится.
стоит создать небольшой воспроизводимый пример и опустить проблему в их репо.
Также обратите внимание, что React.forwardRef
прерывает дрожание деревьев. Лучший способ решить эту проблему - это плагин Babel, который добавляет комментарий /*#__PURE__*/
непосредственно перед React.forwardRef
. Я планирую открыть вопрос об этом для @babel/preset-react
, так как не похоже, что кто-то уже обращался к этому.
Попробуйте рефрактор, чтобы у вас была только одна ссылка на ваш объект снаружи. например, после определения объекта «BareInput» вы присоединяете к нему свойства. Это запутает веб-пакет и не вызовет дрожания деревьев. Что вам нужно сделать, так это поместить объект и его свойства в одну функцию. И у этой функции или класса не должно быть никаких свойств. Попробуйте.
treehaking происходит только тогда, когда mode = production. Попробуйте добавить режим непосредственно в cli, потому что ваш пакет результатов не минимизирован и не убран, поэтому он не находится в рабочем режиме.