簡體   English   中英

如何通過 webpack 4 優化用於搖樹的庫

[英]How to optimize a library for tree-shaking via webpack 4

我正在嘗試更好地學習 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.log(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

而且,我生成的 webpack 包:

!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.log(BareInput);
} ]);

所以我有幾個問題,為什么 BareEmailInput 仍然存在於我的 webpack 包中? 為什么它的處理方式似乎與 BareInput 不同? (即:為什么 forms_es_BareEmailInput 而不僅僅是 BareEmailInput?)

我已經搜索了副作用,但我沒有看到任何副作用,而且我的庫的 package.json 中有sideEffects: false

使用 webpack v4.16.5

嘗試折射,這樣你就只有一個對外部對象的引用。 例如,在定義“BareInput”對象后,您將向其附加屬性。 這會混淆 webpack 並且它不會搖晃。 您需要做的是將對象及其屬性放在單個函數中。 這個函數或類不應該有任何屬性。 試一試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM