This article was first published in Array_Huang Technology blog ——
Practical first
, Without the consent of the author , Do not reprint . Original address :https://segmentfault.com/a/1190000006887523
If you are interested in this series of articles , Welcome to subscribe here :https://segmentfault.com/blog/array_huang
At present, although the front end is in the stage of blooming flowers ,angular/react/vue Competing for , But after all, it is not yet fully mature , Some needs still depend on our big brother jQuery Of .
Personally, I am right jQuery It's not against , But I am jQuery Ecological stagnation is quite helpless , For example, the famous bootstrap( especially 3 generation ), stay webpack You have to rely on a loader Of , I can't keep up with the times . Besides, ,bootstrap It's not bad , There are some jquery The plug-ins haven't been updated for a year or two , even NPM They're not on the shelves , But they just can't find a substitute for them , The project is in a hurry again , What can I do ?
Don't worry. , Today I'll teach you how to adapt to the old style jQuery plug-in unit .
If you put jQuery As a common js Module to load ( Want to use jQuery All the modules of the first require Reuse later ), that , When you load the old jQuery When the plug-in , It often indicates that you can't find jQuery example ( Sometimes it's a hint that you can't find $
), Why is this ?
Explain the problem , You have to explain it a little bit jQuery Plug in mechanism :jQuery Plug in is through jQuery Provided jQuery.fn.extend(object) and jQuery.extend(object) These two methods , To mount the methods implemented by the plug-in itself to jQuery( That is to say ) On this object . Traditional citation jQuery And the way to plug-in is to use <script> load jQuery In itself , Then use the same method to load its plug-in ;jQuery Will be able to jQuery Object set as global variable ( Of course, it also includes
and webpack As a build tool that follows the principle of modularity , Naturally, it is necessary to separate the context of each module to reduce the influence between them ; and jQuery It's already adapted to AMD/CMD And so on , let me put it another way , We are require jQuery
When , It doesn't actually put jQuery
Object set as global variable . Speaking of this , The problem is also obvious ,jQuery Plugins can't find jQuery
Object , Because in their respective contexts , There are no local variables jQuery
( Because there's no fit AMD/CMD, So there's no corresponding require Statement ), There are no global variables jQuery
.
There are many ways , Let's take a look at one by one .
ProvidePlugin
+ expose-loader
First of all, I would like to introduce my most recommended method :ProvidePlugin
+ expose-loader
, Projects in my company , And my personal open source scaffolding project webpack-seed
It's all in this way .
ProvidePlugin The configuration of is as follows :
var providePlugin = new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', 'window.$': 'jquery', });
ProvidePlugin The mechanism is : When webpack Load to some js In the module , There is an undefined name that matches ( The string exactly matches ) Configuration in progress key Of variables , automatically require Configuration in progress value As specified by the js modular .
As in the example above , When an old plug-in uses jQuery.fn.extend(object)
, that webpack It will automatically introduce jquery
( Here I use NPM Version of , I also recommend using NPM Version of ).
in addition , Use ProvidePlugin There's another benefit , Namely , In your own code , Again ! also ! No ! use !require!jQuery! La ! After all, one less sentence is one sentence. Ha ha .
Next up expose-loader, This loader The role of is , Will specify js modular export The variable of is declared as a global variable . Let's take a look expose-loader Configuration of :
/* Obviously this is a loader Configuration item for , Only a limited amount of space is available If you don't understand, go to another article in this series 《webpack Multi page application architecture series ( Two ):webpack What are the common parts of configuration ?》:https://segmentfault.com/a/1190000006863968 */ { test: require.resolve('jquery'), // this loader The goal of the configuration item is NPM Medium jquery loader: 'expose?$!expose?jQuery', // The first jQuery Objects are declared as global variables `jQuery`, It is further declared as a global variable through the pipeline `$` },
You might ask , With ProvidePlugin Why do you need to expose-loader? Good question. , If you have all jQuery Plug ins all use webpack To load , It works ProvidePlugin That's enough ; But the ideal is full , The reality is bone feeling , There are always some needs that can only be used <script>
To load the .
externals yes webpack An item in the configuration , Used to put a global variable “ camouflage ” Into some js Modular exports, Like the following configuration :
externals: { 'jquery': 'window.jQuery', },
that , When a js The module explicitly calls var $ = require('jquery')
When , It will window,jQuery
Back to it .
With the above ProvidePlugin + expose-loader
On the contrary , The plan is to use <script>
Loaded jQuery Satisfy the old-fashioned jQuery The need for plug-ins , Re pass externals Convert it to something that meets the requirements of modularity exports.
I personally don't think much of this practice , After all, that means jQuery Out of the NPM Management of , But some children's shoes have other considerations , For example, in order to speed up the time of each packing jQuery These larger third-party libraries are separated ( Call public directly CDN Third party library ?), It can be regarded as having certain value .
This program is equivalent to the manual version of ProvidePlugin, I used to use requireJS It's the same thing you do when you're doing it , So I started with requireJS Migrate to webpack It's the same way when you use it , Later I learned that there was ProvidePlugin It changed right away .
I won't go into details here , Let's take an example and you can see :
// ./webpack.config.js module.exports = { ... module: { loaders: [ { test: require.resolve("some-module"), loader: "imports?$=jquery&jQuery=jquery", // amount to `var $ = require("jquery");var jQuery = require("jquery");` } ] } };
All of the above plans are actually shimming, Not specifically for jQuery, Please draw inferences from one instance and use . in addition , The above scheme is not only for shimming, For example, use ProvidePlugin
To write less require, Dig more for yourself , It's fun ~~
I have children's shoes. I'm , Said that used my article's plan still prompt $ is not a function
, After my careful analysis , Find out :
ProvidePlugin
+ expose-loader
programme , in other words , He has jquery Packed in .externals: { jquery: 'window.jQuery', },
<script>
To quote jQuery, therefore window.jQuery It's a null.$
That's it. null 了 . In this we can see that ,externals It will cover up ProvidePlugin
Of .
But there's a problem here ,expose-loader
The purpose of this is to set up window.jQuery and window.$, that window.jQuery How could it be null Well ? My guess is :externals stay expose-loader
Set it up window.jQuery
I've taken it before window.jQuery
Value (null
) 了 .
Said so much , In fact, the key meaning is , Don't be cheap. Don't be cheap. Don't be cheap ( Important things are to be repeated for 3 times )!
Look at this series of articles , With me in Github It's better to eat the scaffold project on ( laugh ):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed
).
Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .