تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Problem: Plugin Config Limits0:00

So here's what I'm working on today. I'm doing the final little bits of work to get Laravel Elixir 6 out the door. There's still some lingering webpack issues, so I need to fix that in the next couple of days. Here's what I'm working on right now. This is one from Evan talking about how using Elixir's webpack support, adding additional plugins, like if you want a Vue 2 plugin, can get a little tricky because right now a plugin author can only overload the loaders and not any of the other webpack config. So I did a little brainstorming. Maybe a plugin author could call merge-config, and then you provide your plugin-specific configuration, and then that will be correctly and deeply merged in with our default config. So that's what I'm going to tackle in this episode and in real life. So I have a Sublime project. So we have Laravel Elixir's webpack support, so essentially this is what allows you to do mix.webpack in your projects. But then also,

and in real life. So I have a Sublime project. So we have Laravel Elixir's webpack support, so essentially this is what allows you to do mix.webpack in your projects. But then also, let's say you want to use .vue files. Well, that requires additional configuration. So you install that, and then you require it at the top of your Gulp file, and now you can compile Vue files. So both of those are separate repositories. So let's see what we need to do here. Imagine, right here, this will be like any plugins project. So if you want to take a look at it, it's really simple. It requires Elixir, and then it says, Elixir, when you're ready to go. And in fact, I have no compilation here, so I'm just going to default to regular functions there. But anyways, once Elixir is ready and fully loaded, we're actually going to add some special configuration. And really, that's all this plugin does. It declares a bunch of extensions you need

But anyways, once Elixir is ready and fully loaded, we're actually going to add some special configuration. And really, that's all this plugin does. It declares a bunch of extensions you need in order to compile .vue files, and then it hooks it into Laravel's webpack configuration. So you'll see right here, yeah, so you can overload the loaders. So in this case, we're adding a new webpack loader, and then we're also adding Babel configuration. But right now, yeah, that's kind of all you can do. So if we go back to the actual webpack file, you'll see down here, this is our default webpack config we run. So here are the defaults, but you can also use your own webpack config file. So if you create webpack.config.js in your project root, that will take precedence, or you can pass the fourth argument to mix.webpack, which would be your own webpack configuration that you would want to use. So there's a few

Designing mergeConfig API2:19

project root, that will take precedence, or you can pass the fourth argument to mix.webpack, which would be your own webpack configuration that you would want to use. So there's a few different layers that you could overload the defaults. But anyways, yeah, notice that from the plugin author's point of view, they can modify the loaders, and they can modify Babel support, but they can't add anything else. They can't do anything else like that. So that's what we're trying to fix here. Okay, so let's go back to Laravel Elixir View. We're going to write our perfect code first. So I want to say, and if we go back to Chrome, here's what I suggested, elixir.config.mergeWebpack. Okay, so basically, this will take the place of this. So now what we want to say is, yeah, I just want to access elixir.webpack and then some kind of mergeConfig method. I give it an object of my webpack configuration. Sorry about that. But

this. So now what we want to say is, yeah, I just want to access elixir.webpack and then some kind of mergeConfig method. I give it an object of my webpack configuration. Sorry about that. But anyways, we expect all of this to be properly merged and deeply merged on that note. So for example, if you give an array of loaders, well, I don't want that to override any default loaders that we've defined or that you've defined. So that needs to be properly merged as well. So we need a very smart form of merging here. But anyways, ideally, I think this is what I would want. So let's see. We can get rid of all of that. And this would be our final plugin for modifying configuration. Okay, but right now we know this isn't going to work, right? Because elixir.webpack, that doesn't even exist yet. So here's what we might do. Now here's the entry point. Let's go over this just as a quick recap. So once again, this is what allows you to do mix.webpack in your

Reviewing WebpackTask Flow3:56

that doesn't even exist yet. So here's what we might do. Now here's the entry point. Let's go over this just as a quick recap. So once again, this is what allows you to do mix.webpack in your file. So we begin by declaring some webpack configuration. And then we, this is basically where we bootstrap ourselves. It's almost like a service provider for Elixir, where we say, okay, we're going to extend Elixir with this new method called webpack. And that's going to be handled by this WebpackTask class that I've created. Okay, and then down here, getPaths. This is just how we determine where the source folder should be and where the output folder should be. So if we take a look at WebpackTask, we extend Elixir's task. Now in the constructor, this is one section. So we check to see, did the user create a webpack.config.js file? And if so, we're going to make sure that we use that. So we'll store that as a property. Next, we will lazy load some

So we check to see, did the User create a webpack.config.js file? And if so, we're going to make sure that we use that. So we'll store that as a property. Next, we will lazy load some dependencies. And now here's the actual task. So once again, when you run mix.webpack, ultimately, this is the gulp task that will fire. So grab the source, run it through webpack, handle errors, minify the code, handle any errors with the minify task. And then finally, save the file and display a success notification. Nice and readable. So here's what our webpack compilation looks like. So this records a few steps to the console. And then here, yeah, notice that we are extending, once again, default configuration with any configuration that you might create, with any options that you may pass. And that would probably be rarely used. But just in case, in one particular situation, you want to override a default, you can do that. So here's what I think

Exposing elixir.webpack Config5:32

with any options that you may pass. And that would probably be rarely used. But just in case, in one particular situation, you want to override a default, you can do that. So here's what I think I'm going to do instead. I'm going to grab all of this right here. I'm going to come back. And let's see, this may get messy for just a second, but then we'll clean it up. So I'm just going to say elixir.webpack equals an object. And specifically, the configuration will be this object that I created. Now though, there is one thing that I can't do here, this.output.name. So that's basically figuring out what you specify here. So if you say your source file to public/js/main, well, it's going to figure out what that output is based upon the instance. So I'm going to go ahead and remove that. And I know I'll have to add that later. But at least this way, I can declare some configuration and store it right on the main

feel like a line is too long, and it's also taking too long for me to mentally parse what it does, that's when I extract the method. So in this case, think about it, what am I doing? I'm merging configuration, right? So we're taking our default configuration, merging it with the users, and then merging it with any options that could be passed. So why don't we just defer to a merge.config method, and create that. merge.config, and I'm going to paste that in. But now next, do you remember how we had to remove that one section to declare the output path? So maybe I could say let default.config equal an object, and what did we have there? We had the output, where the file name would be equal to this.output.name. So behind the scenes, we figure out what the output path will be, and then we parse it so that it's an object. And specifically, the name of the file is what we want to use there. Okay,

So behind the scenes, we figure out what the output path will be, and then we parse it so that it's an object. And specifically, the name of the file is what we want to use there. Okay, so now I can return extend our default config. But then, yeah, maybe we could do this. Let's put it on its own line, and I will say merge the webpack.config. Next, though, this is starting to confuse me. elixir.webpack.config, this.webpack.config. What's the difference there? Well, the difference is this is the user's specific configuration. So this is our default config, and this one is the user's configuration. Okay, so I can't read it. It's not clear to me. That means I need to change the name. Why don't we just call it user.webpack.config? And now at least that's a little more clear to me when I come back in a month or two. So now let's go back to our little plugin here.

Why don't we just call it user.webpack.config? And now at least that's a little more clear to me when I come back in a month or two. So now let's go back to our little plugin here. You'll notice, by the way, if this is confusing, in Sublime, I have a project setup. So you're actually seeing three different folders here that are not connected. It's just connected through a Sublime project, which is useful. Anyways, if we come back to our plugin, we want to call this merge.config method. So basically, that's going to take this configuration and merge it with this configuration. But notice, like right here, module loaders. So this is just adding the .view specific loader. Now, if we're not careful and we do kind of a sloppy merge, what's going to happen is that will take precedence over this one. And actually, on that note, I can replace this.

Now, if we're not careful and we do kind of a sloppy merge, what's going to happen is that will take precedence over this one. And actually, on that note, I can replace this. We no longer need to look in the config. We can just hard code this. So our only default loader is a booblay loader. Basically, that just handles ECMAScript 2015 compilation on any .js files. But anyways, yeah, if we do kind of a sloppy merge, what's going to happen is this will override this. And that's not what we want. Really, we want them to be merged together, even if it's an array. So ultimately, once we're done merging, I would want something like this. That's kind of what you want, two different objects. And if you do something like underscore.merge, yeah, by default, that's not going to work. But we can use lodash for that, and it actually works really nicely. So here's what I'm going

Deep Merging With Lodash10:02

And if you do something like underscore.merge, yeah, by default, that's not going to work. But we can use lodash for that, and it actually works really nicely. So here's what I'm going to do. In my package.json file, I am pulling in underscore, but I'm going to remove that here. And instead, I'm going to pull in lodash. Okay, now that has been added here. So if we come back, here's what I can do. I can say import underscore from lodash. And now, if we scroll down, we'll add a new method here called mergeConfig. So this is what any of our plugin authors will use. They will just say elixir.webpack.mergeConfig. And the object, so their config that they are passing in, will be merged with our default config. Let's do that by saying this.config. So take this object, and we're going to make that equal to whatever gets merged. Now, we can use lodash's merge method, but like I said, we want a smart, deeply extended merge that will handle

We do get an object where the module has a loader. But notice, once again, second took the place of first, and that's not what we want. We want loaders to be an array of two items. And by the way, that would do the same thing even if I did merge, because I did not pass a customizer. So yeah, this is going to give us the exact same thing here. Okay. But if we pass a customizer with the object's value and the source value, well, to start, let's just console.log both of those. Okay. Clear this out. Run it again. And whoops. Okay. One more time. So now we have our main console.log. But if we nest down here, we can see the first one is js, the second one is view. So that's what I mean by the value and the source value. So what if we did this? What if we said, what if we said if _.isArray, the object's value. So all we're saying is, as we filter through these, if the property you come to is an array, well, in that case,

now module is equal to two loaders. So maybe that's kind of confusing, but hopefully not. All you're saying is look through these. And if the one, if the property you come to happens to be an array, rather than replacing the original with the new one, instead, we're going to concatenate them together. Okay, so there's our logic we need. I'm going to come back and paste it in here. And once we merge those together, we're going to update our default config. So now our webpack task. Yeah, we just take our default configuration, we merge that with the user's configuration, and then we merge that with any Gulp file specific configuration. So now I am hoping that should do the trick here. So here's our little plugin. When Elixir is ready, then we merge this config with the default config that was declared right here. So here's how I'm going to try this out. Of course, I have a couple tests. But I also what I do for Elixir is I set up a

Testing in Laravel App14:56

merge this config with the default config that was declared right here. So here's how I'm going to try this out. Of course, I have a couple tests. But I also what I do for Elixir is I set up a actual Laravel project, sort of like a sanity check where I install, you can even see some dummy stuff where I was testing out some kind of method. But anyways, where I install the plugins, and I just make sure it works, just like opening up a browser, same thing. So if we switch over there, one way that you can install local repositories is to simply reference a local path. So for example, if I want to pull in the changes that I've made to Laravel Elixir webpack official, then I just pass a path to the project, and it'll pull that in. Okay, great. Next, we're going to pull in one more, we're going to grab the Laravel Elixir view plugin that we've been working on too. Oh, and actually, while it's doing its thing, let me show you a quick little tip.

pull in one more, we're going to grab the Laravel Elixir view plugin that we've been working on too. Oh, and actually, while it's doing its thing, let me show you a quick little tip. So you'll notice that with webpack, I've been using the ECMAScript 2015 code, so classes and such. But I have to compile that down. So a little trick you can use is in your package.json file, you can set up a script. So I can say prepublish, this basically means when I run npm publish to deploy the code. Well, right before you do that, I want you to compile everything down. So compile just takes the source directory right here and sends it through Babel. So it compiles all ECMAScript 2015 code down. So ultimately, when you pull in the extension, you're actually going to be hitting the dist directory, which isn't quite as good to look at, but it's fine. The only files we're interested in are these. Okay, so that seems to be done.

going to be hitting the dist directory, which isn't quite as good to look at, but it's fine. The only files we're interested in are these. Okay, so that seems to be done. Why don't we go ahead and try this out? So here's our Elixir test app. If I go to my gulpfile.js, yeah, you can see some tests I've done here. We're going to try out mix.webpack.js, and I will comment out our plugin. So resources/main.js. To start, let's just say var foo = 'spar'; So let's try that. gulp. And there we go. It compiles down. But next, I'm going to bring it back, and this is where I pull in an alert.vue file. So if we take a look at that, it's just a quick dummy bit of code here. So now, I haven't pulled in Laravel Elixir view, so it should fail, right? Because it's trying to parse a .vue file, but it doesn't know anything about template tags or anything like that.

So now, I haven't pulled in Laravel Elixir view, so it should fail, right? Because it's trying to parse a .vue file, but it doesn't know anything about template tags or anything like that. So now, we install our plugin. And if I run it again, but it fails unexpected missing token in main.js. So let's go back, line 15 or 16. Yeah, we missed the closing object. Okay. So let's go ahead and pull that in one more time and do a quick sanity check. So here's our index file. We set our webpack.config.js. That all looks good. Here's our old stuff, so we can get rid of that entirely. And oh yeah, finally, Babel. Once again, we can just initialize that to an empty object. So let's go ahead and pull that one in as well. And yeah, I think we're all set to go here. So if we run gulp again, yeah, it seems like it's doing its thing. It's compiling everything down. So great. Now, we can verify this. Let's do this. Within, we will need

all set to go here. So if we run gulp again, yeah, it seems like it's doing its thing. It's compiling everything down. So great. Now, we can verify this. Let's do this. Within, we will need to go through our Elixir test app. So Elixir test app, and then we want Elixir.view main.js. Okay. So yeah, we merge the config. So if we start by saying console.log Elixir.webpack.config, and then we compile this down. Yeah, so here's what we had before. That's the default. But if we take all of this and put it down here, we should have merged ours in. And yeah, notice loaders is set to 2. So it is properly merging these two together. And in fact, if you want to see module.loaders, we should see an array of a vue-loader as well as the JS loader. And that's exactly what we want here. And remember, within Elixir test app, webpack official, where is it? Here it is. Yeah, so if we scroll down, if we didn't use mergeWith, so if we just

And that's exactly what we want here. And remember, within Elixir test app, webpack official, where is it? Here it is. Yeah, so if we scroll down, if we didn't use mergeWith, so if we just stuck with merge and we got rid of that entirely, well, yeah, if we run it now, it's going to override it. So the array from the second object would completely take precedence over the array from the first object. So that's why we did this. We wanted to concat or concatenate them together so that they would be merged properly. Or maybe I need to save that. There it is. Cool. So I think that just about does it. So that means if you ever need to add some special plugin for Elixir's webpack support, yeah, I mean, all you'd have to do is listen for when Elixir is ready to go, and then you merge your own configuration into ours. And then in your package.json file, yeah, just pull in whatever it is you need to do.

when Elixir is ready to go, and then you merge your own configuration into ours. And then in your package.json file, yeah, just pull in whatever it is you need to do. So if you need to pull in some special kind of loader and then update your webpack.config file, then this is how you would do it. And we'll see how that goes.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟