├── .gitignore ├── README.md ├── dist ├── main.css └── main.min.js ├── js ├── main.js └── utils.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── scss ├── config │ ├── _global.scss │ └── _vars.scss └── main.scss ├── webpack.config.js ├── webpack_example.info.yml ├── webpack_example.libraries.yml └── webpack_example.theme /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .sass-cache/ 3 | node_modules/ 4 | dist_dev/ 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example Webpack Drupal theme 2 | 3 | This is an example Drupal theme that uses Webpack, and is meant to accompany a 4 | blog post that goes through its features. 5 | 6 | ## Installation 7 | 8 | ```bash 9 | git clone git@github.com:thinkshout/webpack_example.git 10 | cd webpack_example 11 | npm install 12 | ``` 13 | 14 | ## Use 15 | 16 | ```bash 17 | # Start a production build and watch for changes. 18 | npm run start 19 | # Start a development build and watch for changes. 20 | npm run start:dev 21 | # Run a one-time production build. 22 | npm run build 23 | # Run a one-time development build. 24 | npm run build:dev 25 | ``` 26 | 27 | If the `dist_dev` directory exists and your cache is clear, this theme will use 28 | its contents instead of `dist`. The first time you run a development build you 29 | may have to run rebuild caches to see your changes. 30 | -------------------------------------------------------------------------------- /dist/main.css: -------------------------------------------------------------------------------- 1 | body{background:#fff}.blue{color:blue}.red{color:red} 2 | 3 | -------------------------------------------------------------------------------- /dist/main.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/assets/",n(n.s=1)}([function(e,t){e.exports.makeBlue=function(e){e.removeClass("red"),e.addClass("blue")},e.exports.makeRed=function(e){e.removeClass("blue"),e.addClass("red")}},function(e,t,n){n(2),e.exports=n(3)},function(e,t,n){"use strict";n.r(t);var r=n(0);!function(e,t){t.behaviors.myBehavior={attach:function(t,n){e(document).once("my-behavior").on("click",(function(t){e(t.target).hasClass("blue")?Object(r.makeRed)(e(t.target)):Object(r.makeBlue)(e(t.target))}))}}}(jQuery,Drupal)},function(e,t,n){}]); -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | import { makeRed, makeBlue } from './utils.js' 2 | 3 | (($, Drupal) => { 4 | 5 | Drupal.behaviors.myBehavior = { 6 | attach: function (context, settings) { 7 | $(document).once('my-behavior').on('click', function (event) { 8 | if ($(event.target).hasClass('blue')) { 9 | makeRed($(event.target)); 10 | } 11 | else { 12 | makeBlue($(event.target)); 13 | } 14 | }); 15 | } 16 | } 17 | 18 | })(jQuery, Drupal); 19 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | module.exports.makeBlue = ($element) => { 2 | $element.removeClass('red'); 3 | $element.addClass('blue'); 4 | }; 5 | 6 | module.exports.makeRed = ($element) => { 7 | $element.removeClass('blue'); 8 | $element.addClass('red'); 9 | }; 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack_example", 3 | "version": "1.0.0", 4 | "description": "Webpack example", 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "@babel/core": "^7.4.4", 8 | "@babel/preset-env": "^7.4.4", 9 | "autoprefixer": "^9.5.1", 10 | "babel-loader": "^8.0.5", 11 | "browser-sync": "^2.26.7", 12 | "browser-sync-webpack-plugin": "^2.2.2", 13 | "css-loader": "^2.1.1", 14 | "mini-css-extract-plugin": "^0.6.0", 15 | "node-sass": "^4.12.0", 16 | "node-sass-glob-importer": "^5.3.1", 17 | "postcss-loader": "^3.0.0", 18 | "sass-loader": "^7.1.0", 19 | "webpack": "^4.31.0", 20 | "webpack-cli": "^3.3.2" 21 | }, 22 | "scripts": { 23 | "build": "webpack --config webpack.config.js", 24 | "build:dev": "webpack --config webpack.config.js --mode development", 25 | "start": "webpack --watch", 26 | "start:dev": "webpack --watch --mode development" 27 | }, 28 | "author": "ThinkShout, Inc", 29 | "license": "GPL-3.0" 30 | } 31 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer') 4 | ] 5 | }; 6 | -------------------------------------------------------------------------------- /scss/config/_global.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background: $white; 3 | } 4 | -------------------------------------------------------------------------------- /scss/config/_vars.scss: -------------------------------------------------------------------------------- 1 | $blue: blue; 2 | $red: red; 3 | $white: white; 4 | -------------------------------------------------------------------------------- /scss/main.scss: -------------------------------------------------------------------------------- 1 | @import 'config/vars'; 2 | @import 'config/global'; 3 | 4 | .blue { 5 | color: $blue; 6 | } 7 | 8 | .red { 9 | color: $red; 10 | } 11 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const globImporter = require("node-sass-glob-importer"); 2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 3 | const path = require("path"); 4 | const BrowserSyncPlugin = require("browser-sync-webpack-plugin"); 5 | 6 | module.exports = (env, argv) => { 7 | const isDevMode = argv.mode === "development"; 8 | return { 9 | mode: isDevMode ? "development" : "production", 10 | devtool: isDevMode ? "source-map" : false, 11 | entry: { 12 | main: ["./js/main.js", "./scss/main.scss"] 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.scss$/, 18 | use: [ 19 | { 20 | loader: MiniCssExtractPlugin.loader 21 | }, 22 | { 23 | loader: "css-loader", 24 | options: { 25 | sourceMap: true, 26 | modules: false, 27 | localIdentName: "[local]___[hash:base64:5]" 28 | } 29 | }, 30 | { 31 | loader: "postcss-loader", 32 | options: { 33 | sourceMap: true 34 | } 35 | }, 36 | { 37 | loader: "sass-loader", 38 | options: { 39 | importer: globImporter(), 40 | sourceMap: true, 41 | } 42 | } 43 | ] 44 | }, 45 | { 46 | test: /\.js$/, 47 | exclude: /(node_modules|bower_components)/, 48 | use: { 49 | loader: "babel-loader", 50 | options: { 51 | presets: [["@babel/preset-env", { modules: false }]] 52 | } 53 | } 54 | } 55 | ] 56 | }, 57 | output: { 58 | path: isDevMode ? path.resolve(__dirname, "dist_dev") : path.resolve(__dirname, "dist"), 59 | filename: "[name].min.js", 60 | publicPath: "/assets/" 61 | }, 62 | plugins: [ 63 | new MiniCssExtractPlugin(), 64 | new BrowserSyncPlugin({ 65 | host: "localhost", 66 | port: 3000, 67 | proxy: "http://drupal.localhost/" 68 | }) 69 | ] 70 | }; 71 | }; 72 | -------------------------------------------------------------------------------- /webpack_example.info.yml: -------------------------------------------------------------------------------- 1 | name: Webpack example 2 | type: theme 3 | description: An example theme that uses Webpack 4 | package: Other 5 | core: 8.x 6 | libraries: 7 | - webpack_example/main 8 | -------------------------------------------------------------------------------- /webpack_example.libraries.yml: -------------------------------------------------------------------------------- 1 | main: 2 | version: VERSION 3 | css: 4 | theme: 5 | dist/main.css: {} 6 | js: 7 | dist/main.min.js: {} 8 | dependencies: 9 | - core/jquery 10 | - core/drupal 11 | - core/drupalSettings 12 | - core/jquery.once 13 | 14 | dev: 15 | version: VERSION 16 | css: 17 | theme: 18 | dist_dev/main.css: {} 19 | js: 20 | dist_dev/main.min.js: {} 21 | dependencies: 22 | - core/jquery 23 | - core/drupal 24 | - core/drupalSettings 25 | - core/jquery.once 26 | -------------------------------------------------------------------------------- /webpack_example.theme: -------------------------------------------------------------------------------- 1 |