Webpack Module Bundler

Собираем frontend с webpack

Обо мне

Привет. Меня зовут Павел Голован.
JavaScript и Node.js разработчик в компании Intetics.

Тобиас @sokra Копперс

О проекте

Проблемы

Почему Webpack?

По данным https://www.npmjs.com/package/webpack

Почему не Browserify?

Почему Webpack?

Что такое Webpack?

  1. Конфигурационный файл - webpack.config.js
  2. Сборщик
  3. Клиентский скрипт
  4. Загрузчики
  5. Система расширений
  6. Сервер разработки - webpack dev server

wepback.config.js - это Node-модуль

			module.exports = {
				context: `${__dirname}/entries`, // || process.cwd()
				entry: {
					lib: 'lib.js',
					app: 'app.js'
				},
				output: {
					path: `${__dirname}/build`,
					filename: '[name].js'
				}
			}
		

Сборщик

  1. Загружает входные файлы и их зависимости
  2. Разбивает код на фрагменты (chunks)
  3. Оптимизирует
  4. Хэширует
  5. Добавляет модуль к сборке

require

			require('path-to-whatever');
		

Задача: добавлять файл(ы) в сборку динамически

На этапе компиляции доступна переменная logo - имя файла с логотипом. В сборку должен войти только требуемый файл.

Динамический require

			//Directory: './img'
			//Regular expression: /^.*\.svg$/
			require('./img/' + logo + '.svg')
		

require.context

			let imgContext = require.context('img', true, /\.svg$/);
			imgContext.keys().forEach((key) => {
			    if (key === logo) {
					  imgContext(key);
			    }
			});
		

Aliases

			resolve: {
		        root: path.resolve(__dirname),
		        extensions: ['', '.js', '.json'],
	        	alias: {
		            '%config%': `config${ isDebug ?
		    	'-debug' : '' }.json`,
		        }
		    }
		

Aliases

			require('%config%');
		

Aliases

			// Bad
			require('app/components/record/record-edit.js');
			require('app/components/record/record-detail.js');
			// Good
			require('%record%/record-edit.js');
			require('%record%/record-detail.js');
		

Условные выражения

			// platform - это переменная на этапе компиляции
			if (platform === 'native') {
			    require('native-lib.js');			
			}
		

Условные выражения

			// Код на клиенте
			if (true) {
			    require('native-lib.js');			
			}
		

DefinePlugin

DefinePlugin позволяет создавать глобальные константы, значение которых может быть сконфигурировано во время компиляции.

DefinePlugin

			// webpack.config.js
			plugins: [
			    new webpack.DefinePlugin({
			        platform: JSON.stringify(platform)	
			    })  
			]			
		

Smart Chunks

Chunks - это фрагменты кода, которые загружаются и исполняются по требованию, что позволяет уменьшить размер исходного загружаемого файла и загружать код по по мере необходимости.

Smart Chunks

Кэширование

			// Вместо изменения версии вручную
			app_v1_3.js
		

Кэширование

			// Добавляем хэш файла к имени во время сборки
			output: {
			    filename: '[name]-[hash].js'
			}
		

Loaders

Loaders

Loaders

https://webpack.github.io/docs/list-of-loaders.html - 214 loaders!

Global loaders

			// webpack.config.js
			loaders: {
			  [{ test: /\.less$/, loader: 'style!css!less?noIeCompat' }]	
			}
		

Global loaders

			loaders: {
			  [{
					test: /\.js$/,
					loader: 'babel-loader',		
					query: {
						presets: ['es2015'],
						cacheDirectory: true
					}	
			}]	
			}
		

Exports

			//Добавляет в конце модуля
			//module.exports = Handlebars;
			let Handlebars = require('exports?Handlebars!handlebars.js');
		

Imports

			//Добавляет в начале модуля
			//this.App = window.App;
			require('imports?this.App=>window.App!app.js');
		

Script loader

			// Загружает модуль 1 раз игнорируя его зависимости
			require('script!awesome-lib.js');
		

Plugins

CommonsChunkPlugin

			//webpack.config.js
			webpackConfig.entry.vendor = ['lodash', 'moment', 'etc'];
			webpackConfig.plugins = [
			  new webpack.optimize.CommonsChunkPlugin(
				'vendor',
				'vendor.js'
				)
			];
		

ProvidePlugin

			//webpack.config.js
			webpackConfig.plugins = [
			  new webpack.ProvidePlugin({
					Promise: 'bluebird'
				})
			];
		

BannerPlugin

			//webpack.config.js
			webpackConfig.plugins = [
			  new webpack.BannerPlugin(
					'**Bundle License Code**'
				)
			];
		
Future Dashboard
Real Dashboard
Webpack Dashboard

Webpack Dashboard Plugin

Install
npm install webpack-dashboard --save-dev
Use
webpackConfig.plugins = [ new DashboardPlugin() ];
Run
webpack-dashboard -- webpack-dev-server --config ./webpack.config.js

Оптимизация

Webpack Dev Server

Webpack Dev Server configuration

		  output: {
	        path: path.resolve(__dirname, "build"),
		    publicPath: "/assets/",
		    filename: "bundle.js"
		  }
	    

Webpack Dev Server launch

$ webpack-dev-server --inline --content-base build/

Hot Module Replacement

Обновляет клиентский скрипт без перезагрузки страницы

$ webpack-dev-server --hot --inline --content-base build/

Webpack Dev Server launch

Открываем приложение в браузере

http://localhost:8080/assets

What's next? Webpack 2

Fork me on GitHub