KEMBAR78
Utiliser Webpack dans une application Symfony | PDF
Integrate	Webpack
in	a	Symfony	app
How	to	?
1 . 1
Me	?
Lead	Developer
SensioLabs
@al0neh
Alain	Hippolyte
1 . 2
Assetic
Transform	assets	via	filters
Not	in	Symfony	Standard	Edition
anymore
2 . 1
2 . 2
Assetic	drawbacks
Not	the	best	DX
Not	content	aware
Not	frontend	dev	friendly
Poorly	maintained
2 . 3
3 . 1
Module	bundler
3 . 2
Module
one	single	functional	unit
https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript
3 . 3
Bundler
takes	modules	with	dependencies	and
emits	static	assets	representing	those
modules
like	the	Service	Container	in	Symfony
3 . 4
≠
3 . 5
Features
Loads	source	files
Transforms	assets
Produces	asset	bundles
Generates	artifacts	(hashes,	srcmaps)
Great	DX
3 . 6
How	does	it	work	?
3 . 7
3 . 8
The	4	Core	Concepts
Entries	-	Where	to	start	?
Output	-	Where	to	output	?
Loaders	-	How	to	transform	?
Plugins	-	How	to	bundle	?
4 . 1
webpack.config.js
module.exports	=	{
		entry:	{	...	},
		output:	{	...	},
		module:	{
				rules:	[	...	]
		},
		plugins:	[	...	]
};
4 . 2
Entries
//	shortand	syntax
const	config	=	{
		entry:	'./src/app.js'
};
//	Object	syntax
const	config	=	{
		entry:	{
				app:	'./src/app.js',
				vendor:	'./src/vendor.js'
		}
};
Where	to	start?
4 . 3
Output
module.exports	=	{
				output:	{
								path:	'./web/builds',
								filename:	'bundle.js',
								publicPath:	'/builds/'
				}
};
Where	to	output	?
4 . 4
Loaders
module.exports	=	{
				module:	{
								rules:	[
												{
																test:	/.js$/,
																use:	'babel-loader'
												}
								]
				}
};
How	to	transform	?
4 . 5
Common	loaders
Transpiler	:	babel-loader,	ts-loader
Styles	:	css-loader,	style-loader
Files	:	url-loader,	file-loader
Linting	:	jslint-loader
https://webpack.js.org/loaders/
4 . 6
Plugins
module.exports	=	{
				plugins:	[
								new	webpack.optimize.UglifyJsPlugin()
				]
};
https://webpack.js.org/plugins/
bundle-wide	processing
4 . 7
Getting	Started
5 . 1
Agenda
Entry
Configure	Webpack	with	SCSS	files
Import	fonts
5 . 2
Install	Webpack
1/	Make	a	package.json	file
{
		"name":	"sf-live-2017-symfony-webpack",
		"version":	"1.0.0",
		"devDependencies":	{
				"babel-core":	"^6.24.0",
				"babel-loader":	"^6.4.1",
				"webpack":	"^2.2.1"
		}
}
$	npm	install
$	./node_modules/.bin/webpack
5 . 3
My	first	webpack	entry
//	app/Resources/assets/js/main.js
console.log('Symfony	Live	Paris	2017');
{#	app/Resources/views/base.html.twig	#}
<script	src="{{	asset('builds/bundle.js')	}}"></script>
5 . 4
webpack.config.js
module.exports	=	{
				entry:	{
								app:	'./app/Resources/assets/js/app.js',
				},
				output:	{
								path:	'./web/builds',
								filename:	'bundle.js',
								publicPath:	'/builds/'
				},
				module:	{
								rules:	[
												{
																test:	/.js$/,
																exclude:	/(node_modules)/,
																use:	'babel-loader'
												}
								]
				}
};
5 . 5
./node_modules/.bin/webpack
5 . 6
Add	our	sass	loader
//	app/Resources/assets/scss/app.scss
$icon-font-path:	"~bootstrap-sass/assets/fonts/bootstrap/";
@import	"variables";
@import	"~bootstrap-sass/assets/stylesheets/bootstrap";
@import	"bootstrap-theme";
//	app/Resources/assets/js/app.js
import	'../scss/app.scss';
6 . 1
Install	sass	dependencies
module:	{
				rules:	[
								//	...
+							{
+											test:	/.scss$/,
+											use:	[
+															{	loader:	"style-loader"	},
+															{	loader:	"css-loader"	},
+															{	loader:	"sass-loader"	}
+											]
+								}
				]
};
./node_modules/.bin/webpack
$	npm	install	--save-dev	style-loader	css-loader	node-sass	sass-loader
6 . 2
Houston
we	have	a	problem
6 . 3
//	app/Resources/assets/scss/bootstrap.scss
@font-face	{
		font-family:	'Glyphicons	Halflings';
		src:	url(#{$icon-font-path}glyphicons-halflings-regular.eot'));
		//	...
}
6 . 4
Let's	fix	that	!
module.exports	=	{
				module:	{
								rules:	[
												//	...
+											{
+															test:	/.woff2?$|.ttf$|.eot$|.svg$/,
+															use:	"file-loader"
+											}
								]
				}
};
Install	file-loader	dependency
6 . 5
//	app/Resources/assets/saas/main.scss
//	...
@import	"../css/font-awesome-4.6.3.min.css";
@import	"../css/font-lato.css";
@import	"../css/bootstrap-datetimepicker.min.css";
@import	"../css/highlight-solarized-light.css";
@import	"../css/main.css";
Import	other	styles
6 . 6
12
3 4 5
6
1.	 Google	Font	Lato	import
2.	 Bootstrap
3.	 font-lato.css
4.	 bootstrap-datetimepicker.min.css
5.	 highlight-solarized-light.css
6.	 main.css 6 . 7
Summary
Import	a	bootstrap	theme
Use	Webpack	to	transform	SCSS	files
Use	Webpack	to	work	with	fonts
7
Now,	JS
8 . 1
//	app/Resources/assets/js/app.js
import	"../scss/app.scss";
import	"./jquery-2.1.4.min";
import	"./bootstrap-3.3.4.min";
//	...
Common	problem	with	Webpack
Jquery
Inline	JS
8 . 2
Let's	get	fix	them
8 . 3
Jquery
const	jqueryPath	=	'app/Resources/assets/js/jquery-2.1.4.min.js';
module.exports	=	{
				plugins:	[
								new	webpack.ProvidePlugin({
												$:	"jquery",
												jQuery:	"jquery",
												"window.jQuery":	"jquery",
								}),
				],
				resolve:	{
								alias:	{
												jquery:	path.resolve(__dirname,	jqueryPath)
								}
				},
};
8 . 4
//	login.html.twig
{%	block	javascripts	%}
			{#	...	#}
				<script>
								$(document).ready(function()	{
												var	usernameEl	=	$('#username');
												var	passwordEl	=	$('#password');
												if	(!usernameEl.val()	&&	!passwordEl.val())	{
																usernameEl.val('anna_admin');
																passwordEl.val('kitten');
												}
								});
				</script>
{%	endblock	%}
8 . 5
$	npm	install	--save-dev	expose-loader
rules:	[
+				{
+								test:	/jquery/,
+								use:	[
+												{
+																loader:	'expose-loader',
+																options:	'$'
+												},
+												{
+																loader:	'expose-loader',
+																options:	'jQuery'
+												}
+								]
+				}
]
8 . 6
Everything	is
good	!
8 . 7
Webpack	Dev	Server
9 . 1
$	npm	install	--save-dev	webpack-dev-server
module.exports	=	{
				plugins:	[
								new	webpack.HotModuleReplacementPlugin()
				],
				devServer:	{
								hot:	true,
								contentBase:	'./web/'
				},
				devtool:	'inline-source-map',
};
9 . 2
//	app/AppKernel.php
class	AppKernel	extends	Kernel
{
				public	function	registerContainerConfiguration(LoaderInterface	$loader)
				{
								//...
								$loader->load(function($container)	{
												if	($container->getParameter('use_webpack_dev_server'))	{
																$container->loadFromExtension('framework',	[
																				'assets'	=>	[
																								'base_url'	=>	'http://localhost:8080/'
																				]
																]);
												}
								});
				}
}
Ryan	Weaver
./node_modules/.bin/webpack-dev-server
9 . 3
Prepare	for
production
10 . 1
10 . 2
module.exports	=	{
				module:	{
								rules:	[{
																	test:	/.scss$/,
+																use:	ExtractTextPlugin.extract({
+																				fallback:	'style-loader',
+																				use:	['css-loader',	'sass-loader']
+																})
								}]
				},
				plugins:	[
+								new	ExtractTextPlugin('app.css')
				]
};
{#	app/Resources/views/base.html.twig	#}
+{%	block	stylesheets	%}
+				<link	rel="stylesheet"	href="{{	asset('builds/app.css')	}}">
+{%	endblock	%}
Extract	css	into	a	separated	file
10 . 3
Split	vendors	with	CommonChunksPlugin
module.exports	=	{
				entry:	{
								vendor:	[
												'jquery',
												'bootstrap-sass'
								]
				},
				output:	{	filename:	'[name].js'	},
				plugins:	[
								new	webpack.optimize.CommonsChunkPlugin({
												name:	'vendor'
								})
				]
};
{#	app/Resources/views/base.html.twig	#}
{%	block	javascripts	%}
+				<script	src="{{	asset('builds/vendor.js')	}}"></script>
					<script	src="{{	asset('builds/app.js')	}}"></script>
{%	endblock	%}
10 . 4
Minify	with	UglifyJs
Supported	by
Webpack	out	of
the	box	!
module.exports	=	{
				plugins:	[
+								new	webpack.optimize.UglifyJsPlugin({
+												beautify:	false,
+												compress:	{
+																screw_ie8:	true,
+																warnings:	false
+												},
+												mangle:	{
+																screw_ie8:	true,
+																keep_fnames:	true
+												},
+												comments:	false
+								})
				]
};
10 . 5
Minify	our	styles
{
				test:	/.scss$/,
				use:	ExtractTextPlugin.extract({
								fallback:	'style-loader',
								use:	[
												{
																loader:	'css-loader',
																options:	{	//	CSS	Nano	configuration
																				minimize:	{
																								discardComments:	{
																												removeAll:	true
																								},
																								core:	true,
																								minifyFontValues:	true
																				}
																}
												},
												'sass-loader'
								]
				})
}
10 . 6
Long	term	caching
10 . 7
const	WebpackManifestPlugin	=	require('webpack-manifest-plugin');
module.exports	=	{
				output:	{	filename:	'[name].[chunkhash].js'	},
				plugins:	[
								new	WebpackManifestPlugin({
												fileName:	'manifest.json'
								})
				]
};
$	npm	install	--save-dev	webpack-manifest-plugin
Install	Webpack	Manifest	plugin
10 . 8
https://github.com/symfony/symfony/pull/22046
Symfony	3.3
10 . 9
//	app/config/config_prod.yml
framework:
				assets:
								json_manifest_path:	'%kernel.root_dir%/../web/builds/manifest.json'
10 . 10
Tips
11 . 1
Tree	shaking
only	include	code	in	your
bundle	that	is	being	used
https://blog.engineyard.com/2016/tree-shaking
11 . 2
Env	vars
EnvironmentPlugin	:	reference	env	vars
through	process.env
DefinePlugin	:	global	constants
11 . 3
OptimizeJs	Plugin
optimize	a	JavaScript	file	for	faster
initial	execution	and	parsing
https://github.com/vigneshshanmugam/optimize-js-plugin
11 . 4
DedupePlugin
Deduplicate	common	files
https://medium.com/@rajaraodv/two-quick-ways-to-
reduce-react-apps-size-in-production-82226605771a
11 . 5
Thank	you	!
https://joind.in/talk/94c36
https://github.com/alOneh/sf-live-2017-symfony-webpack
12
Questions	?
13

Utiliser Webpack dans une application Symfony