Evan You - Inside Vue Components - Laracon EU 2017

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] so today I'm going to be talking about few components in specific it's about the single file view components that many of you probably have heard of or using some to some extent can I see a show of hands if you've used the single file few components before a lot of you great so so you so a lot of you will have the context what it is but for those you who are not too familiar with it I'm gonna whoa okay okay I'm going to be sort of taking a few steps back and try to talk about why did we come up with this idea and how does it relate to you know the the previous versions of the ways that we used to deal with front-end development in the past and how it sort of relates to relates to how we think about UI development now and then after that I'm going to be digging into some of the technical details if you're not super into JavaScript it might sound a bit too deep for you or but I think it's still worthwhile it's interesting to know if you use view components to some extent those internal technical details will eventually help you sort of demystify this whole thing to some extent all right so let's let's get started and think about way back in the days when we probably when you first started programming with PHP all we think about is this simple model of sending pages from the server to the client and that's pretty much it right every time you click on a link you just go to a new page and we go back to the server let the server find something different to render and then send us back it was all really simple but then these are mostly static pages static pages are not that useful when we try to build applications so then we try to start to add things to these pages and first of course they need to look good so apply these global CSS stylesheets which is sort of straightforward still static pages but then we realize we need to add these little pieces of interactivity hey there's javascript in the browser so why don't we just throwing some JavaScript so we throwing these ad hoc scripts you know make this drop little drop-down or make this a little form a little bit of interactive with some validations but still we are still thinking about mostly in a page based model while when we need some agent interactivity we just broke sprinkled things on to it so this actually works in a lot for a lot of cases if if you're building simple apps this works pretty well and I wouldn't say this is a this is a bad way of doing things because eventually it really depends on your use case but as we know problems always arise when when things scale up when things gets big when your app gets more complex when there are more more more features requested by a manager and the your team grows more and more developers join a team and try to work together eventually you will need to think about maintainability when the things gets big and in our traditional the classic separation concerns we try to think about our because we naturally evolved from this model and we still think in terms of having the the HTML as the base structure we have our Styles apply it on top of it and then we have some extra JavaScript try to manipulate parts of the page so we think in the classic separation concerns and we divide things into templates scripts and styles and then we try to in a lot of you probably try did did this by splitting your bigger templates into smaller ones scripting your multiple Java scripting splitting your big JavaScript file into smaller ones and concatenate them splitting your CSS with import statements or simply concatenate in them but and then we even some of the companies even you know hired developers had grammars based on the language they work with they hire specifically CSS developers JavaScript developers and put them in different groups and expect them to work on the same product and probably a lot of you have learned that this end up causing a lot of back-and-forth and collaboration friction when we're trying to deal with the scripts and style parts that that intrinsically are dealing with the same piece of functionality in this app so this creates problems and the classic separation concerns quickly breaks down when we try to tuck everything into a single page which is trying to deal with more and more content in a single page so so how do we how do we tame this complexity so the natural way of going forwards is people start to think hey a page is a unit of interactivity and if we just think of our UI as nested boxes it's all turtles all the way down and we can you know divide a bigger page into smaller pieces and smaller pieces into even smaller pieces the question is how do we convert our old way of dealing with code to adapt to this new way of thinking about our pages and then we realize it's we can still have a separation of concerns it's just we have to think about on a finer grained level right we are already splitting our template scripts and styles into smaller files right so in the past some of you probably have done the have in our web development source code we have three folders we have j/s CSS and HTML and then we throw files based on the extensions into these folders then some of us started to organize things differently we have this folder count like maybe um header logging form or footer then eat within each folder we have its own Associated template the script and CSS file and the the difficulty is how do we put all these things together and eventually you know assemble them back together although you know separating them into these files made the developers work easier when we're at the stage of deployment there are still a lot of questions so how do we how do we divide this right this seems like a nice way and if we look at them when we pick when we reach into the three folders and find the three files that are intrinsically cup hold to the same piece of functionality they are in fact components right so your header is a component your footer is component login form is a component that can be self-contained and within each of these boundary of responsibility they can have their own separation of concerns between our good old separation concerns between template scripts and styles so it's just a different way of thinking about problem and when we go even one step further and put all three files into the same file we arrive at this single file component format that many of you have seen in the view ecosystem so this is sort of the higher-level thought process of how we arrived at this and a revelation after I personally have tried this paradigm and on many of many other developers who have tried this realized that this colocation of the things that are closely coupled to a single component in the same file is actually pretty awesome right some of you might not add my disagree but we've we found a lot of people kind of kind of like this collocation because it reduces the cost of this mental context switching everything you need for the same component is in the same place you don't have to jump between different file extensions to deal with them and distributing this component also becomes more straightforward as we'll see later in this talk so enter the view components and magic so it's sort of I believe single file view components today works out of the box if you started with a new laravel installation but in the early days before it could sort of had this had this default setup in a fresh level install it wasn't really easy to you know go from Ground Zero and build your configurations all the way up to to get everything working smoothly so this talk is really going to sort of go deep into the technical details and sort of review a lot of the hard work that Geoffrey Wei has been doing behind the scenes in lateral mix and all the related things to simplify all of this for all the level developers so and before we go into the details I want to acknowledge the inspirations I didn't know I did not just invent this out of thin air right so there's a lot of prior art and inspirations and there was this braid project that when I was at Google it kind of started this idea about colocation for me and web components when when they first proposed that things can be just inside the same file was also a great inspiration an attractive is a project by rich harris which also had this format of a component inside a single file idea but it was it was a Umbra in browser transform and the the thing that view did was to take upon these ideas and take a bit step further with build tools and it's a compiled it's a compilation process and why do we choose to do it at compile time right because back in I think 2013 or 14 we so today's browser technology is evolving and we know there are new specs that's coming out like web components and unfortunately I think Google just recently dropped the drop to push for the HTML import spec so this is sort of a reflection of the risk of you know going relying too much on spec that's not formally in place yet and back then when a lot of the web components related technology weren't fully supporting browsers but we wanted all some of the good things about them so how do we get this benefits of these single file components without having to rely on something that's not even in all the browser's yet the answer is we do compile time processing so that we can simulate some of the things that we want at the compile time so that the thing we eventually shipped to browsers don't rely on any new features from the browser's so that's the reason right so back then the first iteration view single file components was actually built with browserify so browserify is a bundler it originally was invented to convert nodejs npm modules which were meant to run on the server side inside nodejs to convert them into a single file of javascript that can run inside the browser and in the process people start to realize because we have this bundling process it's possible to inject these transforms or loaders in web pack term into this bundling process so before we put everything concatenate everything together we have a chance to transform the source coding to something different for example you can transform CoffeeScript into JavaScript which is a very common use case back then today very few people use CoffeeScript anymore but at that time I look at the whole thing and realize this is also a perfect infrastructure if you want to have single file components we just treat the single file components as a source format and then we provide a transform that can somehow parse process compile everything and then eventually just spit out vanilla JavaScript that's how it does right so I wrote a transform code view of i-4 browserify everything all the transforms of browser front ends with efi in so it's just a convention and i wrote that and it worked pretty well and later on webpack became the more dominant bundler and webpack also provided a lot a much more powerful way of handling handling transformed into put individual parts in single file component so I wrote the the loader for few components for wet pack which is the loader okay so here we're going to talk a bit about what the loader actually does right so the first thing we do is we take a single file view file we take a view file and then parse it will parse it into because a view file is essentially syntax wise it's the same as HTML right if you've if you if you've written a simple view like Perl type in fact still I still do write I open up in a single HTML file import view i polling view from a CDN and I just started writing things with with some div elements with some Dom elements a script tag and a style tag and I can instantly load it in the browser and see what's going on and a single file component is essentially that but with some it's it's like a single HTML file on steroids right so we use the same HTML based parser to parse it into three parts template script and style and then thanks to web packs very complex internal structure we can pipe the three parts further into other loaders so we can pipe the template into the view template compiler which is responsible for turning view raw view template strings into JavaScript into render functions and we'll talk about what render functions are later and then the script part of your single file component gets piped through babel loader or TS loader so that we can convert your es2015 or es2016 syntax into es5 javascript that can run in older browsers browsers or if you're into type types you can use typescript and and the style parts we we can pipe them through additional preprocessor string the ball last sass or stylus whatever you prefer and then we pipe it through post CSS which is a Genet general-purpose CSS compiled a shinto l' that allows us to add a bunch more custom stuff into the CSS and eventually we will extract these parties compiled CSS or inject them into our application via JavaScript so this is the bigger picture so the template part we we compare our template into render functions for those of you who've never heard this term a render function in view world is a function that returns virtual Dom well this is in fact the same for react so what is virtual Dom a virtual Dom is lightweight JavaScript data structure to represent what the actual Dom should look like at a given point in time so this might start to sound super abstract but bear with me virtual Dom is essentially you know we have the real Dom structure you have a you can have a div h1 nested P's and spans and think about them as nested JavaScript objects that's pretty much it that's what virtual Dom is and the reason we use a virtual Dom is because it provides the flexibility between templates and raw render functions so we have templates in Vijay s they are extremely approachable they're close to HTML and they are very easy for designers to work with at the same time we we know that the render function or the way virtual Dom works that's pioneered by react provides a very powerful paradigm for working with declarative UI allows you to leverage the full power of JavaScript when you are dealing with extremely complex UI use cases so we want to provide this flexibility for both that's why underneath view uses virtual Dom rendering layer and on top of it we provide this template as an entry point and another benefit of virtual DOM is that ADA couples are apps rendering logic from the browser environment because it's virtual after all right so it no longer relies on the real DOM and means that you can run in other environments for example in nodejs to do server-side rendering it can run in inside a JavaScript engine embedded into a native application so that can power native UI for your projects like weeks or native script in fact in the upcoming version of you we are going to provide a script a more contained version of the view service our renderer which is no longer tightly coupled to no js' which means it can run inside an embedded VA instance so theoretically you can run it in PHP via HPV ajs and you can use view inside laravel has a templating engine so that's something we'd like to see in the future so with all that in mind views rendering pipeline essentially first compiled simply into a render function and returns a virtual Dom and we generate the actual Dom based on virtual Dom and on subsequent updates the render function returns a new virtual Dom and here's where the part that gets interesting we have two copies of virtual Dom and we use some algorithms to diff them to apply the minimum changes to the actual Dom so if you've used react or you view you've read up on on virtual down this might already sound pretty familiar to you but the idea is all of this happens as pure JavaScript right once we are past the first initial compilation phase there's no longer the Dom string that's present so the whole view template syntax the template strings are really just a source format if you're using single file view components after this build phase the code that you shipped to the browser no longer contains any trace of a template they're all turned into vanilla JavaScript so there's a bit more details in here right obviously we need Tylar to do all this compliation and that's going that's provided by view as well this thing actually exists if you're using view directly without any build tools it just runs in the browser does it on the fly but if you're using using single file components you can consider it doing this ahead of time so it's kind of like alt compliation in compiler jargon and it goes through the same same usual compiler compliation steps like parsing the template into an AST so you're did your template of a base template like this gets turned into a data structure like that so we we even have someone even made an app allow you to explore how view templates are turning to the intermediate ast a representation and then the ast is piped into the cogent to generate the actual render functions so taking the takin the ast above we turn them into the code the green part underneath so this may not if you've used to render functions I think this more or less makes sense now but if you haven't used it just just think of it as returning a big tree of JavaScript objects and this is a view template Explorer is an app allows you to explore how your templates are compiled into rehna functions under the hood so yeah so that's a very quick high-level overview of how the template part is handled the the big takeaway is that templates in single file components are just converted into JavaScript and eventually we hold all we get is just a function a string that represents a JavaScript function in in our compilation step phase so okay we're done with templates now let's now next it let's think about styles okay so CSS is traditionally pretty decoupled from our Java Script things because separation concerns but turns out we're thinking about components since this has its own maintainability problem the biggest of it is how do you make sure you don't step on each other's toes because CSS has this natural cascading behavior I mean it's even in its name right cascading stylesheets and the default scope of cascading is global any CSS you write if you write a very generic selector it can affect anything on your page even from HTML that's not written by you right if you have this like h1 selector your code and someone else is write an h1 and it can just unexpectedly affect other people's markup which it's not good so that's why we come we came up with all these ways of trying to tame CSS with naming conventions like BM or all Oh CSS and all that just so that we don't accidentally affect other people's markup but when we think in terms of components it's just what if the CSS you write in side component is just naturally scoped to that component like there's no chance of it ever affecting anything else then you don't even need to think about naming conventions because it's just out of the equation right so this is a one big thing when you when you co-locate your Styles with your component in the same file we get a chance to do some compile time magic to make this seamless and easy for you ok so so the first step of transforming the CSS in your view component is obviously if you opt to use these pre processors like less sass and stylus which is a pretty important use case because I know a lot of designers or developers want to leverage the existing ecosystem of mix-ins or existing libraries written in these pre processors to help them to work more efficiently so this is a optional but not intrusive step we simply take whatever preprocessor you want and transform your CSS and then we pipe it through the CSS loader which is part of the web pack ecosystem the the job CSS loader is really resolving a lot of the URLs in your CSS for example if you are linking linking to a file using a background URL right usually when we deploy CSS we need to think about where the where this file is eventually deployed and how it's it's going to be deployed but it's it's deployed path is relative to the CSS file and where it's deployed and usually these positions these relationships are not the same with the their relative position on the disc as source files that's a lot of headache but with web pack taking care of these resolution it becomes more straightforward you can just you can just link to another image so assets using their relative links using their relative position on as source files on the disk and white pack will rewrite everything to make sure they are eventually in the same in that using the correct path after they are deployed so that's a big bonus and then there is a step of post CSS which is essentially parsing transforming and regenerating the CSS which gives us the opportunity to do the scope simulation I talked just about now so if when you're using single file view components and you add a scoped attribute to your Styles right we generate so we do two things the first thing is we use post CSS to add to to converge all the selectors in the Styles you write to make them more strict we scope them right we if you look at the right the original dot read selector gets converted into a don't rest lecture with an extra attribute selector this limits everything inside that rule down to down to all the elements that only the elements that has that attribute and at the same time because they are in the same file right so we know the same template also needs to be transformed so that every element generated in the same template needs to needs to have that attribute attached to them so this is pure compile-time transform and when when you and it works all the way back in ie9 it doesn't rely on any new browser specs or features right and but it completes the task of scoping your styles in the component to this component only and it doesn't even leak down to child components so you you won't run into the case where you import a child component and this child component is accidentally over its towels accidentally over it and by a parent component of course you can still do that intentionally using the deep selector if you really know what you're doing so this gives us a lot of flexibility at the same time a piece of ease of mind when you're dealing with CSS alternative if you're into CSS modules which is another pretty popular way of dealing with CSS encapsulation we have first-class support for that too and this is also done at compile time we inject the we take the CSS file and convert converts all the class names into a bunch of hash based class names so that they were unique and doesn't overwrite each other and then we expect this inject these class names into your JavaScript so that you can use them directly in your templates okay so after all of that our CSS eventually gets turned into just processed playing CSS that just works directly in your browser all the way back to nine yes and the question comes how do we eventually distribute this compiled CSS right in the past we just think about we were a CSS file directly and we concatenate them and then we push the CSS file up to deployment but wait all your CSS scattered or crossing your components how do we how do we deploy them how are they deployed eventually so the thing is it's actually pretty flexible we can decide at deployment time how to eventually deploy them so one choice is you can extract them using the extract X web path plugin they'll just extract all the CSS from your components put them together into a single file and you get your good old CSS file that you can deploy as usual it's just the CSS file and this method is better because your CSS file gets individual caching so for the launcher make it also reduces the size of the JavaScript undal so it's a little bit but in most cases a little bit better for production but there's another strategy which is leveraging the runtime behavior we can inject we can inline all these processes as in your JavaScript bundle as just strings and then when your JavaScript under runs we dynamically inject the CSS as script tags into into the bread of your document the advantage of this is that because they are individual style tags we can update them dynamically unlike a statically linked to CSS value there's no way you can change it at run time but with style tags in the browser we control the style tag and we can update them dynamically right so Turing development this is critical if we want to have not intrusive reloading of the CSS and this is this is why using this style injection mechanism we enable hot reload during development ok so we've talked about templates and styles and finally script is actually the easy part because simply we just if you if you don't use anything we can just directly take the script as as an es module right because inside a few components we we export our component we using export default this is the syntax for es2015 modules right so your component exports and yet standard es 2015 module and even if you're using babel typescript after everything is compiled it's still a module and the final step is assembling the three things together so remember our template was compounding to JavaScript they are in functions now our CSS if using the a lot if using the extracted strategy then there's nothing really to do here but if you're aligning your CSS to be dynamic looking objected then there are just JavaScript strings and we can then it's also JavaScript so both your template and styles are now JavaScript together with your main JavaScript chunk as an es module we simply attach the render functions and the Styles inline CSS to your main module and then we have finally completed this whole process and got one single ES module out of a single file component and it's pure JavaScript okay so because it's pure JavaScript you can think of it as just a JavaScript file and when you are using it externally you can import them using the JavaScript import syntax you can import foo from food view and what you get is a JavaScript module this means everything that's supposed to work with JavaScript would just work with single file view components so you can do code splitting so this is changing this line to this this is combining the the async component syntax together with the dynamic import in ES syntax plus the web hax code splitting feature so it actually takes takes like we need to explain three things to exam two to fully explain what's going on here but the syntax is simple enough that you can the effort of converting a component that's going to be bundled into your main chunk versus this one what it does is it will split out this full component and all its dependencies into a separate javascript file in this sense this javascript file will be lazy loaded only when the full component needs to be rendered on the string so this is critical to make your initial javascript bundle smaller we are building bigger and bigger applications so when you have this in writing to situations where you have a like jobs robando of one megabyte right think about how long it takes to download and in parson validate and run all this javascript on a phone on a crappy network right it's it's pretty bad so the way to deal with it is we want to lazy load part of our applications and with with the the way single file components work and everything web pack and view provides you it's really straightforward to just split out priority of the application the whole component tree into a separate chunk like this and because they are just files and dependencies you can distribute them as dependencies on as packages on package managers so you can you can distribute them via NPM I imagine you could probably do it with composer as well but I'm not too familiar with you know distributing non PHP files through composer but the the fact that they are just source files means you can you can pack them up and distribute them share them reuse them so this is a great - a great way to share components across across your organization and just remember that if you want to do this you need to whitelist the package from your view loader configuration so that actually knows to process this file alternatively you can pre compile your view single file components into plain JavaScript and then just distribute them as normal JavaScript that'll work - okay so a bonus is talking about hot reload in fact this is one of the sometimes considered more fancy features and I think Jeffrey actually spent quite of effort trying to make it work and personally I think it is a pretty important feature because it makes the development flow much smoother when you're iterating over front-end UI and here I'm just going to try to provide some insight into how it actually works under the hood the first thing is we obviously have our file system containing our review components and in the background we start there is a web pack dev server this web pack dev server watches your files and runs a web pack continuously runs a web pack compiler in the background and whenever you save a file it just recompiles the things that have changed and and then this dev server is connected to your browser to the to the app that you're running so inside your app in addition to your application code there is this like hidden chunk of code that's responsible for receiving events from the dev server so whenever something changed in the dev server it'll send some real-time notifications to this client that's embedded inside your browser this this client obviously only exists during development they're stripped out for production and eventually that's relayed to view hot reload API and we actually do this in a very fine-grain way remember that because each view components splits into so many parts we actually get different separate notifications for each part so if you edit the template and save it will receive a notification that the template has changed if you edit the JavaScript it will receive a notification that the Java Script change and similarly for Styles so we can adopt different hot reloading strategies depending on the type of notification we get if we receive a notification saying your template has changed we can recompile the template because the thing we get is already in an updated version of the compiler and the functions so we simply replace the effected components original rental render function with the new one and tell it to render and we can simply do this because of virtual Dom because virtual Dom re-rendering is essentially doesn't care about it doesn't produce much side effects when we render the virtual Dom it knows how to diff the old virtual Dom with the new one so we can simply tell it to render this is great we don't need to tear it our component and then recreate it which means it preserves the current state of the component so imagine you have you have some UI nested like you need five steps of interaction to finally reach this component that you're currently working on if you when you iterate on this component every time you save your whole page reloads and you have to do the five clicks again to reach that component how much time you're wasting for every change you're making right but with state reserving hot reloading when you after you save the whole app preserve the current state the only thing that's changed is the component you're looking at so so that really helps a lot however if you edit the JavaScript for example so when you edit the JavaScript and things becomes more complicated because potentially you could have edited a lifecycle hook which has some side effects in it you could have edited you could have edited just the whole thing how the component works so it's impossible to infer the potential side effects that's going to be caused by this edit so we're going to do a state resetting reload which completely tears down the current affected component and then we create an instance of them in place the good thing is it doesn't affect its parent component or anything so it only affects the component that that are that has been edited and finally the style parts they are actually updated completely decoupled from our components because we talked about how they are dynamic injecting that script as style tags and if their content change we simply update the content of style tag and the browser will handled the updates for us which is pretty neat so after all of this we talked out a lot about the single file components and its technical details and many times people have asked me um how how are they oh I think I missed a mr. V here they're native components they look a lot like web components right they provide a lot of benefits of web components as well but they are not native and why don't we use native web components so there are in fact a few good reasons why you would for why I personally would lean towards a compiler based strategy versus native component web components today the important thing is today right in the future if everything works as a planned maybe we will all be using web components one day but I believe at this very moment a compiler based strategy still has some considerable advantages the first is you can mix pre processes inside your single file view components right you get to use Park or Jade for your templates you get to use sass les stylus inside your file inside your components you can mix pavel or typescript for your scripts all of these are pretty important dev tools that a lot of us have come to rely on but if you're using native web components there the the workflow for that isn't necessarily the best out there in fact many times you you must stick to the native features that's currently supporting the browser and you have to be constantly thinking about what browsers you're targeting and how much features you can use or not use and all that and hot reload this is just non-existent for web components as far as I know you pretty much have to reload your page less longtime overhead a lot of the work because native web components are essentially purely wrong time most of the work it has to do it has to do dynamically as the as the component is defined it's registered and evaluated and boot up on the page with compile time authorization we can do a lot of work do we can try to do more work ahead of time instead of deferring to the browser so it's essentially you know CPU cycles spend our dev machines is always good compared to CPU cycles spent on your customers machines and no powerful compatibility concerns which in my opinion is one of the biggest reasons that I am still conservative about our web components for most optimization opportunities as we talked about so I didn't talk about some of the compile-time optimizations that we perform when compiling views templates into javascript there are some smart things we can do for example we in fact detect the static trees inside your template so that they don't need to be unnecessarily dipped and updated again and these things are kind of transparent they are they're invisible to the users but we can do it under the hood and we can add more and more these as time goes if you want to without affecting the user's experience the developers experience the developer can largely they can even you know they they don't even need to know about it but we can we are we can still continuously deliver these invisible performance optimizations over time we can do certain rendering with single file components cross-platform rendering and more importantly we're not straight although we try to take the good ideas out of these new specifications we're not really bound to them we're not really bound by this really slow process of trying to take everything into consideration and come up with the perfect specification we get the chance to do fast experimentation we can try all new ideas and although although stability has becoming more important for view JS itself we still get more wiggle room when we're trying to try an all-nude ideas compared to the more rigorous specification process so there are a lot of things to be said here but nevertheless I still think native web components are really good at cross framework or framework agnostic distribution of reusable functionality so that's the place where it'll shine and that's also the place where I think a lot of frameworks will eventually converge at but when you when you're building something from the ground up for your own use I still think the compliation step is really really important in enabling a lot of real benefits here so to sum up the single valued component is a standard source format with extensible compilation pipeline so that gives us a platform to to perform evolution with less churn for the users and that's it thank you [Applause] [Music]
Info
Channel: Laracon EU
Views: 23,656
Rating: undefined out of 5
Keywords: php, amsterdam, laravel, laracon
Id: wZN_FtZRYC8
Channel Id: undefined
Length: 44min 50sec (2690 seconds)
Published: Fri Sep 22 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.