{"id":271395,"date":"2018-05-24T07:22:09","date_gmt":"2018-05-24T14:22:09","guid":{"rendered":"http:\/\/css-tricks.com\/?p=271395"},"modified":"2019-09-17T10:42:39","modified_gmt":"2019-09-17T17:42:39","slug":"learning-gutenberg-6-setting-up-a-custom-webpack-config","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/learning-gutenberg-6-setting-up-a-custom-webpack-config\/","title":{"rendered":"Learning Gutenberg: Setting up a Custom webpack Config"},"content":{"rendered":"

Gutenberg introduces the modern JavaScript stack into the WordPress ecosystem, which means some new tooling should be learned. Although tools like create-guten-block<\/a> are incredibly useful, it\u2019s also handy to know what\u2019s going on under the hood.<\/p>\n

<\/p>\n

\n

Article Series:<\/h4>\n
    \n
  1. \n Series Introduction<\/a>\n <\/li>\n
  2. \n What is Gutenberg, Anyway?<\/a>\n <\/li>\n
  3. \n A Primer with create-guten-block<\/a>\n <\/li>\n
  4. \n Modern JavaScript Syntax<\/a>\n <\/li>\n
  5. \n React 101<\/a>\n <\/li>\n
  6. \n Setting up a Custom webpack (This Post)<\/em>\n <\/li>\n
  7. \n A Custom “Card” Block<\/a>\n <\/li>\n<\/ol>\n<\/div>\n
    The files we will be configuring here should be familiar from what we covered in the Part 2 Primer with create-guten-block<\/a>. If you\u2019re like me (before reading Andy\u2019s tutorial, that is!) and would rather not dive into the configuration part just yet, the scaffold created by create-guten-block matches what we are about to create here, so you can certainly use that as well.<\/div>\n

    Let\u2019s jump in!<\/p>\n

    Getting started<\/h3>\n

    Webpack takes the small, modular aspects of your front-end codebase and smooshes them down into one efficient file. It\u2019s highly extendable and configurable and works as the beating heart of some of the most popular products and projects on the web. It\u2019s very much a JavaScript tool, although it can be used for pretty much whatever you want. For this tutorial, it\u2019s sole focus is JavaScript though.<\/p>\n

    What we\u2019re going to get webpack doing is watch for our changes on some custom block files and compile them with Babel to generate JavaScript files that can be read by most browsers. It\u2019ll also merge any dependencies that we import.<\/p>\n

    But first, we need a place to store our actual webpack setup and front-end files. In Part 2<\/a>, when we poked around the files generated by create-guten-block, we saw that it created an infrastructure for a WordPress plugin that enqueued our front-end files in a WordPress way, and enabled us to activate the plugin through WordPress. I\u2019m going to take this next section to walk us through setting up the infrastructure for a WordPress plugin for our custom block.<\/div>\n

    Setting up a plugin<\/h3>\n

    Hopefully you still have a local WordPress instance running from our primer in Part 2, but if not, you\u2019ll need to have one installed to continue with what we\u2019re about to do. In that install, navigate to wp-content\/plugins<\/code> and create a fresh directory called card-block<\/code> (spoiler alert: we\u2019re going to make a card block… who doesn\u2019t like cards?).<\/p>\n

    Then, inside card-block<\/code>, create a file called card-block.php<\/code>. This will be the equivalent to plugin.php<\/code> from create-guten-block. Next, drop in this chunk of comments to tell WordPress to acknowledge this directory as a plugin and display it in the Plugins page of the Dashboard:<\/p>\n

    <?php\r\n   \/*\r\n   Plugin Name: Card Block\r\n   *\/<\/code><\/pre>\n

    Don\u2019t forget the opening PHP tag, but you can leave the closing one off since we\u2019ll be adding more to this file soon enough.<\/p>\n

    WordPress looks for these comments to register a plugin in the same way it looks for comments at the top of style.css in a theme. This is an abbreviated version of what you\u2019ll find at the top of other plugins\u2019 main files. If you were planning to release it on the WordPress plugin repository, you\u2019d want to add a description and version number as well as license and author information. <\/p>\n

    Go ahead and activate the plugin through the WordPress Dashboard, and I\u2019ll take the steering wheel back to take us through setting up our Webpack config!<\/div>\n

    Getting started with webpack<\/h3>\n

    The first thing we\u2019re going to do is initialize npm<\/a>. Run the following at the root<\/strong> of your plugin folder (wp-content\/plugins\/card-block<\/code>):<\/p>\n

    npm init<\/code><\/pre>\n

    This will ask you a few questions about your project and ultimately generate you a package.json<\/code> file, which lists dependencies and stores core information about your project. <\/p>\n

    Next, let\u2019s install webpack:<\/p>\n

    npm install webpack --save-dev<\/code><\/pre>\n

    You might have noticed that we\u2019re installing webpack locally to our project. This is a good practice to get into with crucial packages that are prone to large, breaking changes. It also means you and your team are all singing off the same song sheet.<\/p>\n

    Then run this:<\/p>\n

    npm install extract-text-webpack-plugin@next --save-dev<\/code><\/pre>\n

    Then these Sass and CSS dependencies:<\/p>\n

    npm install node-sass sass-loader css-loader --save-dev\r\n\r\n# J Parenti wrote in to say that in Babel 7, it's different. You may need to:\r\nnpm uninstall --save-dev sass-loader\r\nnpm install --save-dev sass-loader@7.1.0<\/code><\/pre>\n

    Now, NPX to allow us to use our local dependencies instead of any global ones:<\/p>\n

    npm install npx -g<\/code><\/pre>\n

    Lastly, run this: <\/p>\n

    npm install webpack-cli --save-dev<\/code><\/pre>\n

    That will install the webpack CLI<\/a> for you.<\/p>\n

    Now that we have this installed, we should create our config file. Still in the root of your plugin, create a file called webpack.config.js<\/code> and open that file so we can get coding.<\/p>\n

    With this webpack file, we\u2019re going to be working with traditional ES5 code for maximum compatibility, because it runs with Node JS. You can use ES6 and Babel, but we\u2019ll keep things as simple as possible for this tutorial. <\/p>\n

    Alight, let\u2019s add some constants and imports. Add the following, right at the top of your webpack.config.js<\/code> file:<\/p>\n

    var ExtractText = require('extract-text-webpack-plugin');\r\nvar debug = process.env.NODE_ENV !== 'production';\r\nvar webpack = require('webpack');<\/code><\/pre>\n

    The debug<\/code> var is declaring whether or not we\u2019re in debug<\/code> mode. This is our default mode, but it can be overridden by prepending our webpack commands with NODE_ENV=production<\/code>. The debug<\/code> boolean flag will determine whether webpack generates sourcemaps and minifies the code.<\/p>\n

    As you can see, we\u2019re requiring some dependencies. We know that webpack is needed, so we\u2019ll skip that. Let\u2019s instead focus our attention on ExtractText<\/code>. Essentially, ExtractText<\/code> enables us to pull in files other than JavaScript into the mix. We\u2019re going to need this for our Sass files. By default, webpack assumes everything is JavaScript, so ExtractText<\/code> kind of *translates* the other types of files.<\/p>\n

    Let\u2019s add some config now. Add the following after the webpack<\/code> definition:<\/p>\n

    var extractEditorSCSS = new ExtractText({\r\n  filename: '.\/blocks.editor.build.css'\r\n});\r\n\r\nvar extractBlockSCSS = new ExtractText({\r\n  filename: '.\/blocks.style.build.css'\r\n});<\/code><\/pre>\n

    What we\u2019ve done there is instantiate two instances of ExtractText<\/code> by passing a config object. All that we\u2019ve set is the output of our two block stylesheets. We\u2019ll come to these in the next series, but right now all you need to know is that this is the first step in getting our Sass compiling.<\/p>\n

    OK, after that last bit of code, add the following:<\/p>\n

    var plugins = [ extractEditorSCSS, extractBlockSCSS ];<\/code><\/pre>\n

    Here we\u2019ve got two arrays of plugins. Our ExtractText<\/code> instances live in the core plugins set and we\u2019ve got a couple of optimization plugins that are only smooshed into the core plugins set if we\u2019re not in debug<\/code> mode. We\u2019re running that logic right at the end.<\/p>\n

    Next up, add this SCSS config object:<\/p>\n

    var scssConfig = {\r\n  use: [\r\n    {\r\n      loader: 'css-loader'\r\n    },\r\n    {\r\n      loader: 'sass-loader',\r\n      options: {\r\n        outputStyle: 'compressed'\r\n      }\r\n    }\r\n  ]\r\n};<\/code><\/pre>\n

    This object is going to tell our webpack instance how to behave when it comes across scss<\/code> files. We\u2019ve got it in a config object to keep things as DRY<\/a> as possible.<\/p>\n

    Last up, the meat and taters of the config: <\/p>\n

    module.exports = {\r\n  context: __dirname,\r\n  devtool: debug ? 'inline-sourcemap' : null,\r\n  mode: debug ? 'development' : 'production',\r\n  entry: '.\/blocks\/src\/blocks.js',\r\n  output: {\r\n    path: __dirname + '\/blocks\/dist\/',\r\n    filename: 'blocks.build.js'\r\n  },\r\n  module: {\r\n    rules: [\r\n      {\r\n        test: \/\\.js$\/,\r\n        exclude: \/node_modules\/,\r\n        use: [\r\n          {\r\n            loader: 'babel-loader'\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        test: \/editor\\.scss$\/,\r\n        exclude: \/node_modules\/,\r\n        use: extractEditorSCSS.extract(scssConfig)\r\n      },\r\n      {\r\n        test: \/style\\.scss$\/,\r\n        exclude: \/node_modules\/,\r\n        use: extractBlockSCSS.extract(scssConfig)\r\n      }\r\n    ]\r\n  },\r\n  plugins: plugins\r\n};<\/code><\/pre>\n

    That\u2019s our entire config, so let\u2019s break it down.<\/p>\n

    The script starts with module.exports<\/code> which is essentially saying, “when you import or require me, this is what you\u2019re getting.”<\/em> We can determine what we expose to whatever imports our code, which means we could run code above module.exports<\/code> that do some heavy calculations, for example.<\/p>\n

    Next, let\u2019s look at some of these following properties:<\/p>\n