我試圖使用React和Webpack(3.4.1)構建「組件庫」。這個想法是讓一個React應用程序使用React Cosmos來交互式構建和探索可重用組件的「庫」。該回購還將有一個build
任務,該任務將這些組件編譯成可推送到Github和/或NPM的文件。並且該文件/包可以導入到其他項目中以訪問可重用組件。Webpack包導入空依賴項對象
NOTE/UPDATE - 對於那些誰想要嘗試了這一點,對自己,我已經出版了(非功能性)包NPM:https://www.npmjs.com/package/rs-components。只是
yarn add
它到您的項目(可能)遇到相同的問題。
我有90%的工作 - React Cosmos正確顯示組件,並且我的構建任務(rimraf dist && webpack --display-error-details --config config/build.config.js
)正在運行,沒有錯誤。但是,當我從Github將該回購協議作爲一個包回到另一個項目時,我遇到了錯誤。
錯誤似乎源於Webpack不能正確導入我的組件庫的依賴關係。當我沒有再壓縮/裂傷上建立了圖書館,我進口看到的第一個錯誤是:
TypeError: React.Component is not a constructor
事實上,如果我扔在一個調試器,並檢查它起反應是空物體。
如果我解決,通過(欺騙和)直接導入在node_modules
(const React = require('../../react/react.js')
)編譯/下載的文件反應,不會發生錯誤,但後來我遇到了一個類似的,涉及到在prop-types
庫導入失敗:
TypeError: Cannot read property 'isRequired' of undefined
如此看來,雖然我代碼是否正確得到拉昇,在組件庫文件導入似乎沒有被正確捆綁
這裏是最相關的文件:
配置/ build.config.js
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const config = {
entry: path.resolve(__dirname, '../src/index.js'),
devtool: false,
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
resolve: {
modules: [
path.resolve(__dirname, '../src'),
'node_modules'
],
extensions: ['.js']
},
module: {
rules: []
}
};
// JavaScript
// ------------------------------------
config.module.rules.push({
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
query: {
cacheDirectory: true,
plugins: [
'babel-plugin-transform-class-properties',
'babel-plugin-syntax-dynamic-import',
[
'babel-plugin-transform-runtime',
{
helpers: true,
polyfill: false, // We polyfill needed features in src/normalize.js
regenerator: true
}
],
[
'babel-plugin-transform-object-rest-spread',
{
useBuiltIns: true // We polyfill Object.assign in src/normalize.js
}
]
],
presets: [
'babel-preset-react',
['babel-preset-env', {
targets: {
ie9: true,
uglify: false,
modules: false
}
}]
]
}
}]
});
// Styles
// ------------------------------------
const extractStyles = new ExtractTextPlugin({
filename: 'styles/[name].[contenthash].css',
allChunks: true,
disable: false
});
config.module.rules.push({
test: /\.css$/,
use: 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]'
});
config.module.rules.push({
test: /\.(sass|scss)$/,
loader: extractStyles.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
sourceMap: false,
minimize: {
autoprefixer: {
add: true,
remove: true,
browsers: ['last 2 versions']
},
discardComments: {
removeAll: true
},
discardUnused: false,
mergeIdents: false,
reduceIdents: false,
safe: true,
sourcemap: false
}
}
},
{
loader: 'postcss-loader',
options: {
autoprefixer: {
add: true,
remove: true,
browsers: ['last 2 versions']
},
discardComments: {
removeAll: true
},
discardUnused: false,
mergeIdents: false,
reduceIdents: false,
safe: true,
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false,
includePaths: [
path.resolve(__dirname, '../src/styles')
]
}
}
]
})
});
config.plugins = [extractStyles];
// Images
// ------------------------------------
config.module.rules.push({
test: /\.(png|jpg|gif)$/,
loader: 'url-loader',
options: {
limit: 8192
}
});
// Bundle Splitting
// ------------------------------------
const bundles = ['normalize', 'manifest'];
bundles.unshift('vendor');
config.entry.vendor = [
'react',
'react-dom',
'redux',
'react-redux',
'redux-thunk',
'react-router'
];
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({ names: bundles }));
// Production Optimizations
// ------------------------------------
config.plugins.push(
new webpack.LoaderOptionsPlugin({
minimize: false,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: false,
comments: false,
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true
}
})
);
module.exports = config;
一個例子組件:
Checkbox.js
import React from 'react';
import { connect } from 'react-redux';
import { map } from 'react-immutable-proptypes';
import classnames from 'classnames';
import { setCheckboxValue } from 'store/actions';
/**
* Renders a Redux-connected Checkbox with label
*
* @param {string} boxID - Unique string identifier of checkbox
* @param {string} name - Label text to display
* @param {function} dispatch - Redux dispatch function
* @param {Immutable.Map} checkboxes - Redux checkboxes Map
* @param {string[]} className - Optional additional classes
*
* @returns {React.Component} A checkbox with globally-tracked value
*/
export function CheckboxUC ({ boxID, name, dispatch, checkboxes, className }) {
const checked = checkboxes.get(boxID);
return (
<label className={ classnames('checkbox rscomp', className) } htmlFor={ boxID }>
<input
className="checkable__input"
type="checkbox"
onChange={() => {
dispatch(setCheckboxValue(boxID, !checked));
} }
name={ name }
checked={ checked }
/>
<span className="checkable__mark" />
<span className="checkable__label">{ name }</span>
</label>
);
}
const mapStateToProps = state => ({
checkboxes: state.checkboxes
});
const { string, func } = React.PropTypes;
CheckboxUC.propTypes = {
boxID: string.isRequired,
name: string.isRequired,
checkboxes: map.isRequired,
dispatch: func,
className: string
};
export default connect(mapStateToProps)(CheckboxUC);
與「條目」文件中的WebPack建設任務(webpack --config config/build.config.js
),這是指僅導出,應該是由應用程序導入此包可訪問的組件:
的src /指數。JS
import BaseForm from 'components/BaseForm';
import Checkbox from 'components/Checkbox';
import Dropdown from 'components/Dropdown';
import Link from 'components/Link';
import RadioGroup from 'components/RadioGroup';
import { validators } from 'components/BaseForm/utils';
export default {
BaseForm,
Checkbox,
Dropdown,
Link,
RadioGroup,
utils: {
validators
}
};
最後,這裏是在編譯未變醜JS行被 「進口」 的變量,似乎不當未定義:
var React = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(3);
讓我知道是否還有其他東西可以幫助解決這個問題。超級困惑,所以我非常感謝任何幫助。
謝謝!
編輯
的事一堆做似乎正確導入。當我在編譯的文件中拋出一個調試器,並看看__webpack_require__(n)
嘗試一大堆不同的n
s時,我看到不同的導入模塊。不幸的是,React和PropTypes似乎並不在其中。