我需要一些帮助,因为我很难在使用react-starter-kit模板(https://github.com/kriasoft/react-starter-kit)创建的新项目中尝试使用bootstrap和react-bootstrap。
我对webpack很陌生,所以我不确定我需要做些什么才能让它正常工作。
到目前为止我所做的步骤:
1)我在package.json中包含了react-bootstrap,bootstrap和jquery 2)我在home文件中导入了react-bootstrap按钮并尝试渲染。它完全没有风格。
还有什么需要做的?
这是webpack.config:
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-present Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
import path from 'path';
import webpack from 'webpack';
import AssetsPlugin from 'assets-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import pkg from '../package.json';
const isDebug = !process.argv.includes('--release');
const isVerbose = process.argv.includes('--verbose');
const isAnalyze = process.argv.includes('--analyze') || process.argv.includes('--analyse');
//
// Common configuration chunk to be used for both
// client-side (client.js) and server-side (server.js) bundles
// -----------------------------------------------------------------------------
const config = {
context: path.resolve(__dirname, '..'),
output: {
path: path.resolve(__dirname, '../build/public/assets'),
publicPath: '/assets/',
pathinfo: isVerbose,
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, '../src'),
],
query: {
// https://github.com/babel/babel-loader#options
cacheDirectory: isDebug,
// https://babeljs.io/docs/usage/options/
babelrc: false,
presets: [
// A Babel preset that can automatically determine the Babel plugins and polyfills
// https://github.com/babel/babel-preset-env
['env', {
targets: {
browsers: pkg.browserslist,
},
modules: false,
useBuiltIns: false,
debug: false,
}],
// Experimental ECMAScript proposals
// https://babeljs.io/docs/plugins/#presets-stage-x-experimental-presets-
'stage-2',
// JSX, Flow
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
'react',
// Optimize React code for the production build
// https://github.com/thejameskyle/babel-react-optimize
...isDebug ? [] : ['react-optimize'],
],
plugins: [
// Adds component stack to warning messages
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
...isDebug ? ['transform-react-jsx-source'] : [],
// Adds __self attribute to JSX which React will use for some warnings
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
...isDebug ? ['transform-react-jsx-self'] : [],
],
},
},
{
test: /\.css/,
use: [
{
loader: 'isomorphic-style-loader',
},
{
loader: 'css-loader',
options: {
// CSS Loader https://github.com/webpack/css-loader
importLoaders: 1,
sourceMap: isDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: true,
localIdentName: isDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]',
// CSS Nano http://cssnano.co/options/
minimize: !isDebug,
discardComments: { removeAll: true },
},
},
{
loader: 'postcss-loader',
options: {
config: './tools/postcss.config.js',
},
},
],
},
{
test: /\.md$/,
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
},
{
test: /\.txt$/,
loader: 'raw-loader',
},
{
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
loader: 'file-loader',
query: {
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
},
},
{
test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
loader: 'url-loader',
query: {
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
limit: 10000,
},
},
],
},
// Don't attempt to continue if there are any errors.
bail: !isDebug,
cache: isDebug,
stats: {
colors: true,
reasons: isDebug,
hash: isVerbose,
version: isVerbose,
timings: true,
chunks: isVerbose,
chunkModules: isVerbose,
cached: isVerbose,
cachedAssets: isVerbose,
},
};
//
// Configuration for the client-side bundle (client.js)
// -----------------------------------------------------------------------------
const clientConfig = {
...config,
name: 'client',
target: 'web',
entry: {
client: ['babel-polyfill', './src/client.js'],
},
output: {
...config.output,
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
},
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': true,
__DEV__: isDebug,
}),
// Emit a file with assets paths
// https://github.com/sporto/assets-webpack-plugin#options
new AssetsPlugin({
path: path.resolve(__dirname, '../build'),
filename: 'assets.json',
prettyPrint: true,
}),
// Move modules that occur in multiple entry chunks to a new entry chunk (the commons chunk).
// http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: module => /node_modules/.test(module.resource),
}),
...isDebug ? [] : [
// Minimize all JavaScript output of chunks
// https://github.com/mishoo/UglifyJS2#compressor-options
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
screw_ie8: true, // React doesn't support IE8
warnings: isVerbose,
unused: true,
dead_code: true,
},
mangle: {
screw_ie8: true,
},
output: {
comments: false,
screw_ie8: true,
},
}),
],
// Webpack Bundle Analyzer
// https://github.com/th0r/webpack-bundle-analyzer
...isAnalyze ? [new BundleAnalyzerPlugin()] : [],
],
// Choose a developer tool to enhance debugging
// http://webpack.github.io/docs/configuration.html#devtool
devtool: isDebug ? 'cheap-module-source-map' : false,
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
// https://webpack.github.io/docs/configuration.html#node
// https://github.com/webpack/node-libs-browser/tree/master/mock
node: {
fs: 'empty',
net: 'empty',
tls: 'empty',
},
};
//
// Configuration for the server-side bundle (server.js)
// -----------------------------------------------------------------------------
const serverConfig = {
...config,
name: 'server',
target: 'node',
entry: {
server: ['babel-polyfill', './src/server.js'],
},
output: {
...config.output,
filename: '../../server.js',
libraryTarget: 'commonjs2',
},
module: {
...config.module,
// Override babel-preset-env configuration for Node.js
rules: config.module.rules.map(rule => (rule.loader !== 'babel-loader' ? rule : {
...rule,
query: {
...rule.query,
presets: rule.query.presets.map(preset => (preset[0] !== 'env' ? preset : ['env', {
targets: {
node: parseFloat(pkg.engines.node.replace(/^\D+/g, '')),
},
modules: false,
useBuiltIns: false,
debug: false,
}])),
},
})),
},
externals: [
/^\.\/assets\.json$/,
(context, request, callback) => {
const isExternal =
request.match(/^[@a-z][a-z/.\-0-9]*$/i) &&
!request.match(/\.(css|less|scss|sss)$/i);
callback(null, Boolean(isExternal));
},
],
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': false,
__DEV__: isDebug,
}),
// Do not create separate chunks of the server bundle
// https://webpack.github.io/docs/list-of-plugins.html#limitchunkcountplugin
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
// Adds a banner to the top of each generated chunk
// https://webpack.github.io/docs/list-of-plugins.html#bannerplugin
new webpack.BannerPlugin({
banner: 'require("source-map-support").install();',
raw: true,
entryOnly: false,
}),
],
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
devtool: isDebug ? 'cheap-module-source-map' : 'source-map',
};
export default [clientConfig, serverConfig];
然后是package.json:
{
"name": "web",
"version": "0.0.0",
"private": true,
"engines": {
"node": ">=6.5",
"npm": ">=3.10"
},
"browserslist": [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 9"
],
"dependencies": {
"babel-polyfill": "^6.23.0",
"bluebird": "^3.5.0",
"body-parser": "^1.17.1",
"classnames": "^2.2.5",
"cookie-parser": "^1.4.3",
"core-js": "^2.4.1",
"express": "^4.15.2",
"express-graphql": "^0.6.4",
"express-jwt": "^5.3.0",
"fastclick": "^1.0.6",
"graphql": "^0.9.3",
"history": "^4.6.1",
"isomorphic-fetch": "^2.2.1",
"isomorphic-style-loader": "^2.0.0",
"jsonwebtoken": "^7.3.0",
"normalize.css": "^6.0.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"pretty-error": "^2.1.0",
"prop-types": "^15.5.8",
"query-string": "^4.3.4",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"serialize-javascript": "^1.3.0",
"source-map-support": "^0.4.14",
"universal-router": "^3.1.0",
"bootstrap": "^3.3.7",
"react-bootstrap": "^0.30.0",
"jquery": "^2.2.1",
"bootstrap-webpack": "0.0.3"
},
"devDependencies": {
"assets-webpack-plugin": "^3.5.1",
"autoprefixer": "^6.7.7",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-plugin-rewire": "^1.1.0",
"babel-preset-env": "^1.4.0",
"babel-preset-react": "^6.24.1",
"babel-preset-react-optimize": "^1.0.1",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.24.1",
"babel-template": "^6.24.1",
"babel-types": "^6.24.1",
"browser-sync": "^2.18.8",
"chai": "^3.5.0",
"chokidar": "^1.6.1",
"css-loader": "^0.28.0",
"editorconfig-tools": "^0.1.1",
"enzyme": "^2.8.2",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^14.1.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-css-modules": "^2.7.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.3",
"file-loader": "^0.11.1",
"front-matter": "^2.1.2",
"glob": "^7.1.1",
"json-loader": "^0.5.4",
"lint-staged": "^3.4.0",
"markdown-it": "^8.3.1",
"mkdirp": "^0.5.1",
"mocha": "^3.3.0",
"pixrem": "^3.0.2",
"pleeease-filters": "^3.0.1",
"postcss": "^5.2.17",
"postcss-calc": "^5.3.1",
"postcss-color-function": "^3.0.0",
"postcss-custom-media": "^5.0.1",
"postcss-custom-properties": "^5.0.2",
"postcss-custom-selectors": "^3.0.0",
"postcss-flexbugs-fixes": "^2.1.1",
"postcss-global-import": "^1.0.0",
"postcss-import": "^9.1.0",
"postcss-loader": "^1.3.3",
"postcss-media-minmax": "^2.1.2",
"postcss-nested": "^1.0.1",
"postcss-nesting": "^2.3.1",
"postcss-pseudoelements": "^4.0.0",
"postcss-selector-matches": "^2.0.5",
"postcss-selector-not": "^2.0.0",
"pre-commit": "^1.2.2",
"raw-loader": "^0.5.1",
"react-addons-test-utils": "^15.5.1",
"react-deep-force-update": "^2.0.1",
"react-hot-loader": "^3.0.0-beta.6",
"redbox-react": "^1.3.6",
"rimraf": "^2.6.1",
"sinon": "^2.1.0",
"stylefmt": "^5.3.2",
"stylelint": "^7.10.1",
"stylelint-config-standard": "^16.0.0",
"url-loader": "^0.5.8",
"webpack": "^2.4.1",
"webpack-bundle-analyzer": "^2.4.0",
"webpack-dev-middleware": "^1.10.2",
"webpack-hot-middleware": "^2.18.0",
"write-file-webpack-plugin": "^4.0.2"
},
"babel": {
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
],
"stage-2",
"react"
],
"env": {
"test": {
"plugins": [
"rewire"
]
}
}
},
"stylelint": {
"extends": "stylelint-config-standard",
"rules": {
"string-quotes": "single",
"property-no-unknown": [
true,
{
"ignoreProperties": [
"composes"
]
}
],
"selector-pseudo-class-no-unknown": [
true,
{
"ignorePseudoClasses": [
"global"
]
}
]
}
},
"lint-staged": {
"*.{cmd,html,json,md,sh,txt,xml,yml}": [
"editorconfig-tools fix",
"git add"
],
"*.{js,jsx}": [
"eslint --fix",
"git add"
],
"*.{css,less,scss,sss}": [
"stylefmt",
"stylelint",
"git add"
]
},
"scripts": {
"lint:fix": "eslint --fix src tools",
"lint:js": "eslint src tools",
"lint:css": "stylelint \"src/**/*.{css,less,scss,sss}\"",
"lint:staged": "lint-staged",
"lint": "yarn run lint:js && yarn run lint:css",
"test": "mocha \"src/**/*.test.js\" --require babel-register --require test/setup.js",
"test:watch": "yarn run test -- --reporter min --watch",
"clean": "babel-node tools/run clean",
"copy": "babel-node tools/run copy",
"bundle": "babel-node tools/run bundle",
"build": "babel-node tools/run build",
"build:stats": "yarn run build -- --release --analyse",
"deploy": "babel-node tools/run deploy",
"render": "babel-node tools/run render",
"serve": "babel-node tools/run runServer",
"start:brk": "babel-node --debug-brk tools/run start",
"start:dev": "babel-node tools/run start",
"start": "node build/server.js"
}
}
最后是我的Home.js
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-present Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Home.css';
import {Button} from 'react-bootstrap';
class Home extends React.Component {
static propTypes = {
news: PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
content: PropTypes.string,
})).isRequired,
};
render() {
return (
<div className={s.root}>
<div className={s.container}>
<h1>React.js News</h1>
<Button bsStyle="primary">Primary</Button>
</div>
</div>
);
}
}
export default withStyles(s)(Home);
答案 0 :(得分:2)
您需要手动添加引导程序CSS:
因为React-Bootstrap不依赖于非常精确的Bootstrap版本,所以我们不附带任何包含的CSS。
在src/components/Html.js
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css">
用法(例如:Home.js)
<Button bsStyle="primary">Default</Button>
<h1>React.js News</h1>
<Alert bsStyle="warning"> Hello </Alert>
请看一下: