Repack-Bootstrap与Webpack无法使用react-starter-kit

时间:2017-05-01 21:33:11

标签: javascript twitter-bootstrap-3 webpack webpack-2 react-bootstrap

我需要一些帮助,因为我很难在使用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);

1 个答案:

答案 0 :(得分:2)

您需要手动添加引导程序CSS:

  

因为React-Bootstrap不依赖于非常精确的Bootstrap版本,所以我们不附带任何包含的CSS。

More info here

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>

请看一下:

https://github.com/kriasoft/react-starter-kit/pull/782

https://github.com/kriasoft/react-starter-kit/issues/950