Upload
alain-hippolyte
View
796
Download
5
Embed Size (px)
Citation preview
IntegrateWebpackinaSymfonyapp
Howto?
1 . 1
Me?
LeadDeveloperSensioLabs@al0neh
AlainHippolyte
1 . 2
AsseticTransformassetsviafiltersNotinSymfonyStandardEditionanymore
2 . 1
2 . 2
AsseticdrawbacksNotthebestDXNotcontentawareNotfrontenddevfriendlyPoorlymaintained
2 . 3
3 . 1
Modulebundler
3 . 2
Moduleonesinglefunctionalunit
https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript3 . 3
BundlertakesmoduleswithdependenciesandemitsstaticassetsrepresentingthosemodulesliketheServiceContainerinSymfony
3 . 4
≠
3 . 5
FeaturesLoadssourcefilesTransformsassetsProducesassetbundlesGeneratesartifacts(hashes,srcmaps)GreatDX
3 . 6
Howdoesitwork?
3 . 7
3 . 8
The4CoreConceptsEntries-Wheretostart?Output-Wheretooutput?Loaders-Howtotransform?Plugins-Howtobundle?
4 . 1
webpack.config.js
module.exports={entry:{...},output:{...},module:{rules:[...]},plugins:[...]};
4 . 2
Entries//shortandsyntaxconstconfig={entry:'./src/app.js'};
//Objectsyntaxconstconfig={entry:{app:'./src/app.js',vendor:'./src/vendor.js'}};
Wheretostart?
4 . 3
Output
module.exports={output:{path:'./web/builds',filename:'bundle.js',publicPath:'/builds/'}};
Wheretooutput?
4 . 4
Loaders
module.exports={module:{rules:[{test:/\.js$/,use:'babel-loader'}]}};
Howtotransform?
4 . 5
Commonloaders
Transpiler:babel-loader,ts-loaderStyles:css-loader,style-loaderFiles:url-loader,file-loaderLinting:jslint-loader
https://webpack.js.org/loaders/4 . 6
Plugins
module.exports={plugins:[newwebpack.optimize.UglifyJsPlugin()]};
https://webpack.js.org/plugins/
bundle-wideprocessing
4 . 7
GettingStarted
5 . 1
AgendaEntryConfigureWebpackwithSCSSfilesImportfonts
5 . 2
InstallWebpack1/Makeapackage.jsonfile
{"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"}}
$npminstall$./node_modules/.bin/webpack
5 . 3
Myfirstwebpackentry
//app/Resources/assets/js/main.js
console.log('SymfonyLiveParis2017');
{#app/Resources/views/base.html.twig#}
<scriptsrc="{{asset('builds/bundle.js')}}"></script>
5 . 4
webpack.config.jsmodule.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
Addoursassloader
//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
Installsassdependencies
module:{rules:[//...+{+test:/\.scss$/,+use:[+{loader:"style-loader"},+{loader:"css-loader"},+{loader:"sass-loader"}+]+}]};
./node_modules/.bin/webpack
$npminstall--save-devstyle-loadercss-loadernode-sasssass-loader
6 . 2
Houstonwehaveaproblem
6 . 3
//app/Resources/assets/scss/bootstrap.scss
@font-face{font-family:'GlyphiconsHalflings';src:url(#{$icon-font-path}glyphicons-halflings-regular.eot'));//...}
6 . 4
Let'sfixthat!
module.exports={module:{rules:[//...+{+test:/\.woff2?$|\.ttf$|\.eot$|\.svg$/,+use:"file-loader"+}]}};
Installfile-loaderdependency
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";
Importotherstyles
6 . 6
12 3 4 5
6
1. GoogleFontLatoimport2. Bootstrap3. font-lato.css4. bootstrap-datetimepicker.min.css5. highlight-solarized-light.css6. main.css
6 . 7
Summary
ImportabootstrapthemeUseWebpacktotransformSCSSfilesUseWebpacktoworkwithfonts
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";//...
CommonproblemwithWebpack
JqueryInlineJS
8 . 2
Let'sgetfixthem
8 . 3
JqueryconstjqueryPath='app/Resources/assets/js/jquery-2.1.4.min.js';module.exports={plugins:[newwebpack.ProvidePlugin({$:"jquery",jQuery:"jquery","window.jQuery":"jquery",}),],resolve:{alias:{jquery:path.resolve(__dirname,jqueryPath)}},};
8 . 4
//login.html.twig{%blockjavascripts%}{#...#}<script>$(document).ready(function(){varusernameEl=$('#username');varpasswordEl=$('#password');
if(!usernameEl.val()&&!passwordEl.val()){usernameEl.val('anna_admin');passwordEl.val('kitten');}});</script>{%endblock%}
8 . 5
$npminstall--save-devexpose-loader
rules:[+{+test:/jquery/,+use:[+{+loader:'expose-loader',+options:'$'+},+{+loader:'expose-loader',+options:'jQuery'+}+]+}]
8 . 6
Everythingisgood!
8 . 7
WebpackDevServer
9 . 1
$npminstall--save-devwebpack-dev-server
module.exports={plugins:[newwebpack.HotModuleReplacementPlugin()],devServer:{hot:true,contentBase:'./web/'},devtool:'inline-source-map',};
9 . 2
//app/AppKernel.phpclassAppKernelextendsKernel{publicfunctionregisterContainerConfiguration(LoaderInterface$loader){//...$loader->load(function($container){if($container->getParameter('use_webpack_dev_server')){$container->loadFromExtension('framework',['assets'=>['base_url'=>'http://localhost:8080/']]);}});}}
RyanWeaver
./node_modules/.bin/webpack-dev-server
9 . 3
Prepareforproduction
10 . 1
10 . 2
module.exports={module:{rules:[{test:/\.scss$/,+use:ExtractTextPlugin.extract({+fallback:'style-loader',+use:['css-loader','sass-loader']+})}]},plugins:[+newExtractTextPlugin('app.css')]};
{#app/Resources/views/base.html.twig#}+{%blockstylesheets%}+<linkrel="stylesheet"href="{{asset('builds/app.css')}}">+{%endblock%}
Extractcssintoaseparatedfile
10 . 3
SplitvendorswithCommonChunksPluginmodule.exports={entry:{vendor:['jquery','bootstrap-sass']},output:{filename:'[name].js'},plugins:[newwebpack.optimize.CommonsChunkPlugin({name:'vendor'})]};
{#app/Resources/views/base.html.twig#}{%blockjavascripts%}+<scriptsrc="{{asset('builds/vendor.js')}}"></script><scriptsrc="{{asset('builds/app.js')}}"></script>{%endblock%}
10 . 4
MinifywithUglifyJs
SupportedbyWebpackoutof
thebox!
module.exports={plugins:[+newwebpack.optimize.UglifyJsPlugin({+beautify:false,+compress:{+screw_ie8:true,+warnings:false+},+mangle:{+screw_ie8:true,+keep_fnames:true+},+comments:false+})]};
10 . 5
Minifyourstyles{test:/\.scss$/,use:ExtractTextPlugin.extract({fallback:'style-loader',use:[{loader:'css-loader',options:{//CSSNanoconfigurationminimize:{discardComments:{removeAll:true},core:true,minifyFontValues:true}}},'sass-loader']})}
10 . 6
Longtermcaching
10 . 7
constWebpackManifestPlugin=require('webpack-manifest-plugin');
module.exports={output:{filename:'[name].[chunkhash].js'},plugins:[newWebpackManifestPlugin({fileName:'manifest.json'})]};
$npminstall--save-devwebpack-manifest-plugin
InstallWebpackManifestplugin
10 . 8
https://github.com/symfony/symfony/pull/22046
Symfony3.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
Treeshaking
onlyincludecodeinyourbundlethatisbeingused
https://blog.engineyard.com/2016/tree-shaking
11 . 2
EnvvarsEnvironmentPlugin:referenceenvvarsthroughprocess.envDefinePlugin:globalconstants
11 . 3
OptimizeJsPlugin
optimizeaJavaScriptfileforfasterinitialexecutionandparsing
https://github.com/vigneshshanmugam/optimize-js-plugin11 . 4
DedupePlugin
Deduplicatecommonfiles
https://medium.com/@rajaraodv/two-quick-ways-to-reduce-react-apps-size-in-production-82226605771a
11 . 5
Thankyou!
https://joind.in/talk/94c36
https://github.com/alOneh/sf-live-2017-symfony-webpack
12
Questions?
13