Webpack til The Fast and The Furious

Også offentliggjort i min tech-blog

Dette er en guide, der er beregnet til at hjælpe dig med at lette din udviklingsworkflow og spare din tid ved at bruge en masse fantastiske værktøjer, som du har læst om på internettet (ringer React Hot Loader nogen klokker?)

Det er også beregnet til at hjælpe dig med nogle af de mest almindelige problemer, mens du bruger Webpack - og spare lidt tid i processen, før du begynder at trække dit hår ud. Når alt kommer til alt, vil du gå hurtigt og rive igennem andre vigtige problemer.

Chancerne er, at du er stødt på et eller flere af følgende problemer:

  • Hvordan har jeg flere poster?
  • Hvordan shim-moduler?
  • Et af de biblioteker / plugins, jeg bruger, afhænger af jQuery, hvordan håndterer jeg det?
  • Jeg bliver ved med at få $ er ikke defineret eller noget dumt lort som det i et af jQuery Plugins
  • Min bundling tager ligesom for evigt at afslutte.
  • Jeg læste en masse tutorials om hvordan moduludskiftning til ReactJS og synes, det er virkelig sejt, men fortsæt med at løbe ind i fejl, mens jeg konfigurerer det.

Hvis du løber ind i disse vanskeligheder, skal du afslutte denne artikel, før du griber til at sende et af disse spørgsmål i Stack Overflow.

Jeg antager, at du allerede ved om fordelene ved Webpack, og hvad det bruges til. Hvis du er nybegynder og ikke har nogen anelse om, hvad Webpack er, anbefaler jeg stærkt, at du læser om det her.

Jeg antager også, at du bygger en webapp og ikke bare en statisk side, hvilket betyder, at du vil have en webserver, der kører på Node og Express. Du bruger sandsynligvis også en NodeJS-driver til at tale med din database - sandsynligvis MongoDB eller Redis.

Så her ser en typisk webpack.config.js ud:

/** * @Author Ashwin Hariharan * @Details Webpack config file for adding new vendors, defining entry points and shimming modules. */ var webpack = require('webpack'); var path = require("path"); var lib_dir = __dirname + '/public/libs', node_dir = __dirname + '/node_modules'; // bower_dir = __dirname + '/bower_components' var config = { resolve: { alias: { react: node_dir + '/react', reactDom: lib_dir + '/react-dom', jquery: lib_dir + '/jquery-1.11.2.min.js', magnificPopup: lib_dir + '/jquery.magnific-popup.js' //JQuery Plugin } }, entry: { app: ['./public/src/js/app-main'], vendors: ['react','reactDom','jquery','magnificPopup'] }, output: { path: path.join(__dirname, "public"), filename: "dist/js/[name].bundle.js" }, plugins: [ new webpack.ProvidePlugin({ jQuery: "jquery", 'window.jQuery': "jquery" }), new webpack.optimize.CommonsChunkPlugin('vendors', 'dist/js/vendors.js', Infinity), ], module: { noParse: [ new RegExp(lib_dir + '/react.js'), new RegExp(lib_dir +'/jquery-1.11.2.min.js') ], loaders: [ { test: /\.js$/, loader: 'babel', query: { presets: ['react', 'es2015'] } }, ] } }; module.exports = config;

Denne konfiguration forudsætter, at du har brugt nogle node-moduler og dist-version af få biblioteker gemt i en public / libs- mappe. Hvis du nu har læst andre vejledninger, forstår du, hvad konfigurationerne i denne fil gør, men jeg vil stadig kort forklare, hvad få ting i denne fil er til -

  • Aliaser / leverandører

    Her inkluderer du alle dine biblioteker / nodemoduler / andre leverandører og kortlægger hver af dem til aliaser. Så hvis du bruger et modul i en hvilken som helst del af din applikationslogik, kan du skrive dette (i din app-main.js eller en hvilken som helst anden JS-fil):

var React = require(‘react’); var ReactDom = require('reactDom'); var $ = require('jquery'); //Your application logic

Eller hvis du foretrækker AMD frem for CommonJS:

define( [ ‘react’, ’reactDom’, ’jquery’ ], function(React, ReactDom, $) { //Your application logic } );

Eller også i ES6:

import React from 'react'; import ReactDom from 'reactDom'; import $ from 'jquery';
  • Definere dine indgangspunkter
entry: { }

Denne blok i din konfiguration giver Webpack mulighed for at bestemme, hvor din app begynder at blive udført, og den opretter klumper ud af den. At have flere indgangspunkter i din applikation er altid en fordel. Især kan du tilføje alle dine leverandørfiler - som jQuery og ReactJS - i et stykke. På denne måde forbliver dine leverandørfiler de samme, selv når du ændrer dine kildefiler.

Så i ovenstående konfiguration er der to indgangspunkter. En til din apps indgang, hvor din JS begynder, og en til dine leverandører - hver af dem kortlagt til et variabelt navn.

  • Dit outputkatalog og bundtfilnavne
output: { path: path.join(__dirname, “public”), filename: “dist/js/[name].bundle.js” },

Denne blok fortæller Webpack, hvad dine filer skal navngives efter byggeprocessen, og hvor de skal placeres. I vores eksempel har vi to poster med navnet app og leverandører , så efter byggeprocessen har du to filer kaldet app.bundle.js og vendors.bundle.js inde i / public / dist / js- biblioteket.

  • Plugins

Webpack leveres med et rigt økosystem af plugins, der hjælper med at imødekomme specifikke behov. Jeg forklarer kort nogle af de mest anvendte:

  • Brug CommonsChunkPlugin til at få Webpack til at bestemme, hvilken kode / moduler du bruger mest, og læg den i en separat pakke, der skal bruges overalt i din applikation.
  • Du kan eventuelt bruge ProvidePlugin til at injicere globaler. Der er mange jQuery-plugins, der er afhængige af en global jQuery-variabel som $, så ved hjælp af dette plugin kan Webpack forberede var $ = require ("jquery") hver gang det møder den globale $ identifikator. Ditto for ethvert andet plugin derude, som Bootstrap.

Ved at inkludere noParse kan du bede Webpack om ikke at analysere bestemte moduler. Dette er nyttigt, når du kun har dist version af disse moduler / biblioteker. Forbedrer byggetiden.

  • Læssemaskiner

Hvis du nu skriver JSX i din React-kode, kan du enten bruge jsx-loader eller babel-loader til at præ-kompilere JSX til JavaScript. Så du kan køre npm install jsx-loader og inkludere dette i din konfiguration:

loaders: [ { test: /\.js$/, loader: 'jsx-loader' }, ]

Men hvis du skriver din kode i JSX og ES6, skal du bruge babel-loader sammen med babel-pluginet til React. Så kør npm install babel-core babel-loader babel-preset-es2015 babel-preset-react, og tilføj derefter dette til din konfiguration i stedet for ovenstående.

loaders: [ { test: /\.js$/, loader: ‘babel’, query: { presets: [‘react’, ‘es2015’] }, include: path.join(__dirname, ‘public’) } ]

På samme måde har du læssere til at kompilere TypeScript, CoffeeScript osv.

Eksempel

  • Din webserverfil:
var http = require("http"); var express = require("express"); var consolidate = require('consolidate'); var handlebars = require('handlebars'); var bodyParser = require('body-parser'); var routes = require('./routes'); var app = express(); //Set the folder-name from where you serve the html page. app.set('views', 'views'); //For using handlebars as the template engine. app.set('view engine', 'html'); app.engine('html', consolidate.handlebars); //Set the folder from where you serve all static files like images, css, javascripts, libraries etc app.use(express.static('./public')); app.use(bodyParser.urlencoded({ extended: true })); var portNumber = 8000; http.createServer(app).listen(portNumber, function(){ console.log('Server listening at port '+ portNumber); app.get('/', function(req, res){ console.log('request to / received'); res.render('index.html'); }); });
  • app-main.js hvorfra vores front-end-logik begynder:
define( [ ‘react’, ’reactDom’, ’./components/home-page’ ], function(React, ReactDom, HomePage){ console.log(‘Loaded the Home Page’); ReactDom.render(, document.getElementById(‘componentContainer’)); } );
  • home-page.js er vores overordnede React-komponent, som kunne indeholde noget som dette:
define(['react', 'jquery', 'magnificPopup'], function(React, $) { var HomePage = React.createClass({ getInitialState: function() { return { userName: 'ashwin' } }, componentDidMount: function() { $('.test-popup-link').magnificPopup({ type: 'image' // other options }); }, render: function() { return ( {this.state.userName} Open popup ); } }); return HomePage; });

Opening your terminal, going to your project’s root folder and running webpack will create two files: vendors.bundle.js and app.bundle.js. Include these two files in your index.html and hit //localhost:8000 in your browser. This will render a component with your username displayed on the web page.

Now, as you work more on Webpack, you’ll get frustrated by constantly having to build your files manually to see changes reflected on your browser. Wouldn’t it be awesome if there was a way to automate the build process every time you make a change to a file? So if you’re tired of typing the command webpack and hitting the refresh button on your browser every time you change a class name, do read on…

Automating Builds with Webpack Dev Server and React Hot Loader

We will use this awesome module called Webpack Dev Server. It’s an express server which runs on port 8080 and emits information about the compilation state to the client via a socket connection. We will also use React Hot Loader which is plugin for Webpack that allows instantaneous live refresh without losing state while editing React components.

  • Step 1: So go run npm install webpack-dev-server — save-dev and then npm install react-hot-loader — save-dev

Then you need to tweak your Webpack config a little to use this plugin. In your loaders, add this before any other loader:

{ test: /\.jsx?$/, loaders: [‘react-hot’], include: path.join(__dirname, ‘public’) }

This tells Webpack to use React Hot Loader for your components. Make sure React Hot Loader comes before Babel in the loaders array. Also make sure you have include: path.join(__dirname, ‘public’) to avoid processing node_modules, or you may get an error like this:

Uncaught TypeError: Cannot read property ‘NODE_ENV’ of undefined

  • Step 2: Changes to your index.html

If your index.html has something like this:

Change this to point to your webpack-dev-server proxy:

  • Step 3: Run webpack-dev-server --hot --inline,

wait for the bundling to finish, then hit //localhost:8000 (your express server port) in your browser.

If you run into any errors while setting up React Hot Loader, you’ll find this troubleshooting guide and this awesome answer on Stack Overflow on Managing jQuery Plugin Dependency with Webpack very helpful. In addition, you can take a look at the Webpack setup for my projects here and here.

This is only meant for development. While in production, you need to minify all your files. Just running webpack -p will minify/uglify/concatenate all your files.

Wouldn’t it be awesome if there was a way to view all your file dependencies in a beautiful tree-like visualization? There is a web-app which does that.

Kør webpack - profil - json> stats.j son i din terminal . Dette genererer en JSON-fil kaldet stats.json. Gå til //webpack.github.io/analyse/, og upload filen, så ser du alle afhængigheder i en trælignende struktur.

Kan du lide det, du læser? Du skal abonnere. Jeg spilder ikke din tid.