« Previous Tutorial Next Tutorial »

Our code’s fully DRYed out, and now we’re going to make things a bit prettier. To do that we’re going to bring in the latest version of Twitter’s venerable Bootstrap framework. The main reasons I’m choosing Bootstrap are: a. because tons of people are already familiar with it and b. so that we can use a module called Reactstrap, which will allow us to use its built-in React components to quickly generate Bootstrap-friendly HTML. If you’re into Bootstrap 3, there’s another great module called React-Bootstrap that works with that version, but I like the new, flexbox-friendly, Sass-driven version 4.

We’re going to be ingesting bootstrap in a way that’s mildly weird. Instead of just calling the CSS via an HTML <style> tag, we’re going to import it into our JavaScript, then use a parsing plugin for Webpack that will pull out the CSS and serve it as a separate file. This way we’ll be able to make changes to the CSS, if we want, and have Webpack automatically compile them, rather than having to run a separate compiler like Gulp (or the Sass Ruby gem, which is not just a whole other tutorial, but an entirely different tutorial series and possibly website).

So, let’s do this. The first thing we have to do is install a whole bunch of modules, which you may notice is a running theme. If you’re worried that your bundle size might be getting ridiculous, that’s good! It probably is. We’ll do at least one tutorial, probably more, on ways to mitigate this issue, since serving 8 MB of JavaScript over the web is a certified bad idea. But right now everything’s local and super-fast, so let’s get it running first, and optimize afterward.

Head to your terminal window or command prompt, and type the following:

yarn add reactstrap react-addons-transition-group react-addons-css-transition-group bootstrap@4.0.0-alpha.6 extract-text-webpack-plugin css-loader style-loader

This covers Reactstrap, some helper utilities for Bootstrap transitions, Bootstrap itself, and the plugins and loaders we’ll need to get Webpack to do what we want it to do. Once all that’s done installing, head for Sublime Text and let’s get this stuff running. Start by opening webpack.config.js … we don’t actually have to make too many changes here, but we need to address a few things. First, below line 2, let’s add our extract text plugin, like this:

const ExtractTextPlugin = require('extract-text-webpack-plugin');

Now, look at line 14:

    filename: 'build.js',

and line 16:

    publicPath: '/javascripts',

While we’re going to take steps to have our server generate a different filename for our CSS, that /javascripts is a problem, because it means our server’s going to try to serve our styles from that directory. Which, I mean, whatever … you can import CSS from any directory, but it’s just a bad look, you know?

So, let’s change line 14 to this:

    filename: 'javascripts/build.js',

and line 16 to this:

    publicPath: '/',

There. Now we’ll be able to serve our CSS from wherever we want. Let’s do that. We need to add a rule set to the rules array, under the module object. We already have one, for handling .jsx files. Now we need one for handling .css files. Below line 27, add the following code:

      {
        test: /\.css?$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader',
        }),
      },

What we’re doing here is saying “when you encounter a CSS file, parse it with our extract text plugin, using css-loader to resolve all imports and URLs in the CSS, and then pipe that output to style-loader, which will actually write the generated CSS out.” We’ll be adding another step in here eventually to deal with Sass, but right now we’re just dealing with Bootstrap’s pre-built CSS files.

Last but not least, we need to add our text extraction plugin to Webpack’s list of plugins, so just below line 40, add the following:

new ExtractTextPlugin('stylesheets/style.css'),

This is telling our plugin where to serve the file, which, since in our output we just set our public path to “/”, means it’ll live at “/stylesheets/style.css” … which is where it belongs. Woo!

Speaking of which, we have an existing file of the same name in the actual, physical /public/stylesheets/ folder that can cause conflicts. It comes with Express and has about eight lines in it. Delete the file entirely, either via the command line or in Sublime Text.

We’re done with Webpack config. Save that file. Now let’s make a few small tweaks to our components to use some Bootstrap stuff. First, open /src/index.jsx and add the following code to line 3:

import 'bootstrap/dist/css/bootstrap.css';

This gives Webpack access to the Bootstrap css. Save the file. Next, open /src/components/Template.jsx and change line 13 to look like this:

<section className="page-content container-fluid">

Save the file, and open up /src/components/home/HomePage.jsx and just below the first line, add the following:

import { Button } from 'reactstrap';

Now we’re going to do something interesting … add a helper function to this component. Below line 5, add this code:

const showAlert = () => {
  alert('You clicked the button. Well done, Draco!');
};

Now make a quick tweak to line 13, so that our columns will work on medium-sized screens (like, for example, the MacBook Pro on which this is being typed/recorded). Just change the “lg” to an “md” instead.

      <div className="col-sm-12 col-md-8">

And let’s replace all of our inner content with some new stuff. Replace:

This is the home page.

with:

        <p>
          This is the home page.
        </p>
        <p>
          Here for your enjoyment is a button:
        </p>
        <Button onClick={showAlert}>Click Me</Button>

See that onClick? Some of you may be getting that thing where your eyelid twitches uncontrollably, right now. Yes, it’s true, we’ve spent the past decade-plus talking about not using HTML onClicks in favor of catching events with JavaScript. Here’s the thing: we’re still doing that. It’s just that React is doing that for us. It’s taking that simple onClick, and turning it into a JavaScript event catcher. If you were to check your Button element in the element inspector, you’d see that there’s no “onClick” generated on the finalized HTML output. So, take a breath, we’re all good!

Save that file, and let’s move on to /src/components/account/ProfilePage.jsx where we’re just, for now, going to make the same column tweak, so change “lg” to “md,” on line 9, like this:

      <div className="col-sm-12 col-md-8">

Save the file, and move on to /src/components/shared/Sidebar.jsx. We’re going to make this a little prettier and add a Bootstrap card just for the heck of it. Just below line 1, add this code:

import { Card, CardBlock, CardText } from 'reactstrap';

now swap out the “lg” for an “md” on line 6 like this:

<aside className="col-sm-12 col-md-4">

And swap out the following text on line 7:

      This is the new sidebar component.

with all of this:

      <Card>
        <CardBlock>
          <CardText>
            Sidebar Item
          </CardText>
        </CardBlock>
      </Card>

Save that file, and we’re good to go. Make sure your Express server is running, and head for a browser pointed at localhost:3000. You may need to do a hard-refresh here to get the styles to show up, but everything should be working, including our alert when we click our button on the homepage.

All right. We have Bootstrap. Well done, Draco! In our next tutorial, we’re going to build out a login page. Stay tuned!

« Previous Tutorial Next Tutorial »