Глубокое погружение в webpack

Владимир Кузнецов (@mistakster), Graph

Глубокое погружение в webpack

Владимир Кузнецов, @mistakster, Graph

FrontTalks, сентябрь 2015

Для чего нужен webpack?

Grunt и Gulp vs. webpack

Grunt и Gulp vs. webpack

Это не просто «task runner»

Что полезного он умеет?

Дерево зависимостей

Пример с CommonJS модулями

			var shuffle = require("lodash/collection/shuffle");
			var camelCase = require("lodash/string/camelCase");
			module.exports = function (list) {
			  return shuffle(list).map(camelCase);
			};
		

Зависимостями могут быть любые файлы

Загрузчики и плагины

Загрузчки

Плагины

Конфигурация webpack

Конфигурация webpack

			module.exports = {
			  entry: "./app.js",
			  output: {
        	    path: __dirname + "/output",
        	    filename: "app.bundle.js"
    		  }
    		};
		
Конфигурация webpack

Явно указываем файл конфигурации

			$ webpack --config ./configs/site.js
			$ webpack --config ./configs/admin.js
		
Real doge

Many boring tasks

Such automation
So webpack

Обнаружение общих модулей

Несколько точек входа

			entry: {
			  "site": "./site",
			  "admin": "./admin"
			}
		

Параметры финальной упаковки

			output: {
			  path: require("path").resolve("./public/_/"),
			  publicPath: "/assets/",
			  filename: "[name].js",
			  chunkFilename: "[id].chunk.js"
			}
		

Обнаружение общих модулей

			plugins: [
			  new webpack.optimize.CommonsChunkPlugin({
			    name: "commons",
			    filename: "[name].js"
			  })
			]
		

Загрузка общей части

			<-- site.html -->
			<script src="/assets/commons.js"></script>
			<script src="/assets/site.js"></script>
		

Автоматическое разделение кода на части

Code splitting

			require.ensure(["jquery", "lodash"],
			  function (require) {
			    var jQuery = require("jquery");
			  }
			);
		
Переходи на HTTPS!

bundle-loader

			var waitForChunk = require('bundle!./page');
			waitForChunk(function (page) {
			  page.init();
			});
		

Подавляем ненужные ресурсы

Контекст

			// moment.js
			require("./locale/" + name);
		

Папка — ./locale
Регулярное выражение — /^.*$/

Подавляем ненужные ресурсы

			plugins: [
			  new webpack.ContextReplacementPlugin(
			    /moment[\/\\]locale$/,
			    /^(en-gb|ru)\.js$/
			  )
			]
		

Плагины для оптимизации упаковки

Плагины для оптимизации упаковки

Глобальные переменные

			new webpack.DefinePlugin({
			  "DEBUG": process.env.NODE_ENV != "production",
			  "API_ENDPOINT": "'" + URL + "'",
			  "helloWorldFunc": function () {
			    return 'Hello, world!';
			  }
			})
		

Глобальные переменные

					if (DEBUG) {
					 alert(API_ENDPOINT);
					}
					helloWorldFunc();
				
					if (false) {
					 alert(('http://example.com'));
					}
					(function () {
					 return 'Hello, world!';
					})();
				

Сервер для разработки и горячее обновление

Сервер для разработки

			$ npm i -g webpack-dev-server
			$ webpack-dev-server
		

Можно встроить в существующий сервер на Node.js или пробросить доступ к нему через прокси-сервер.

Извлечение стилей из упаковки

Стили на страницу добавляются динамически

Конфигурируем плагин

			var ExtractText = require("extract-text-webpack-plugin");
			var extractStyles = new ExtractText("main.css");
			var loader = extractStyles.extract("style", "css!less");
		

Добавляем плагин и загрузчик

			plugins: [ extractStyles ]
			module: {
			  loaders: [
			    { test: /\.less$/, loader: loader }
			  ]
			}
		
Сгенерированные ресурсы

Бонус: запуск задач

Запуск задач плагином

			var MyTaskRunner = function () {};
			MyTaskRunner.prototype.apply = function (compiler) {
			  // задачи
			}
			module.exports = MyTaskRunner;
		

Запуск задач плагином

			compiler.plugin("run", function (params, callback) {
			  console.log("*** Run ***");
			  callback();
			});
			compiler.plugin("done", function () {
			  console.log("*** Done ***");
			});
		

Запуск задач

			$ npm run clean
		
			"scripts": {
			  "clean": "rm -rf ./public/_"
			}
		

Запуск задач

			$ npm run build:site
			$ npm run build:admin
		

$ npm run build:site

			"scripts": {
			  "build:site": "./node_modules/.bin/webpack --config site…
			  "build:admin": "./node_modules/.bin/webpack …
			}
		

Запуск задач

			$ npm run myCoolJavaScript
		
			"scripts": {
			  "myCoolJavaScript": "node my-cool-javascript.js"
			}
		

Заключение

С погружением!

Владимир Кузнецов

@mistakster (English)
@mista_k (больше про жизнь)

noteskeeper.ru

Слайды презентации: mistakster.github.io/fronttalks-webpack