The global introduction of the front end of modernization is an interesting thing. Take a look at the following scenarios:
- In Webpack, we can define a higher-level directory in resolve’s alias as a custom variable. For example,
resolve: { alias: { '@': path.join(__dirname, '.. ', 'src') }}
. - In Webpack, we can also use DefinePlugin to classify configuration files according to environment variables, and efficiently complete the introduction of configuration files according to environment, whether development build or production build, is very useful.
- In Vue, we can define a common method or library on vue.ptototye, either directly or via plugin install in Vue. For example,
Vue.prototype.$_ = lodash
In the context of an application where VUE is applied, a reference to LoDash can be obtained via this.$_. - In Vue, there are also mixins, Inject, vuex and other global binding or mixin, injection global introduction implementation.
Let’s think about this:
If we bind too many third party libraries to vue. prototype, will the root Vue be too big? The answer is yes. Is there a way around this? You might say, I don't use this.xxx. Use vue single file components directly import or require. What if hundreds, thousands or even tens of thousands of.vue files are used? All the way through? I can keep introducing. But it will cause unnecessary work.Copy the code
Is there a more elegant solution?
Let’s consider another question:
What if I want to use LoDash in an xxx.js file where WebPack covers? Normally, we would just 'import _ from' lodash'' or 'const _ = require('lodash')'. What if, like.vue, there are many, many JS files to import? All the way through? I can keep introducing. It also creates unnecessary work.Copy the code
Is there a more elegant way to do it?
Look at the graph that introduces the moment 99 times to get a sense of it:
Although I’m optimizing the introduction of moment in my project, I’ll use the introduction of LoDash as an example for clarity.
- There are three ways to use the ProvidePlugin
- Why do you keep introducing unnecessary work
- Introduce practices using the ProvidePlugin
- Add $_ configuration to webpack plugins
- Globals of ESLint adds a $_ configuration
- How to use $_ in Vue
- Considerations for using templates in Vue
- Why is this the most recommended?
- So why not mount it on data?
- thinking
- Will the ProvidePlugin reduce the packaging volume over time?
- What are the considerations when using ProvidePlugin?
- What is the injected ProvidePlugin?
There are three ways to use the ProvidePlugin
/ / grammar
new webpack.ProvidePlugin({
identifier: 'module1'.// identifier: ['module1', 'property1'],
});
Copy the code
- module.exports
- Directly introducing
- Introduce some function
- export default
module.exports
Directly introducing
new webpack.ProvidePlugin({
The $_: 'lodash'});Copy the code
Introduce some function
new webpack.ProvidePlugin({
$_uniqBy: ['lodash'.'uniqBy']});Copy the code
export default
new webpack.ProvidePlugin({
Vue: ['vue/dist/vue.esm.js'.'default']});Copy the code
Why do you keep introducing unnecessary work
We have 26 js files from a to Z, a.js to Z.js, each of which needs to import LoDash.
// a.js
importThe $_from 'lodash';
// b.js
importThe $_from 'lodash';
// c.js
importThe $_from 'lodash';
// d.js
importThe $_from 'lodash';
// e.js
importThe $_from 'lodash';
// f.js
importThe $_from 'lodash'; .// z.js
importThe $_from 'lodash';
Copy the code
This has several drawbacks
- Do it 26 times
- User-defined names after import may be inconsistent, making global search difficult
The following scenario, for example, is bad for code readability.
// a.js
importThe $_from 'lodash';
// b.js
import _ from 'lodash';
Copy the code
Introduce practices using the ProvidePlugin
- Add $_ configuration to webpack plugins
- Globals of ESLint adds a $_ configuration
- How to use $_ in Vue
- Considerations for using templates in Vue
Add $_ configuration to webpack plugins
// webpack.base.config.js
plugins: [
new webpack.ProvidePlugin({
The $_: 'lodash',})],Copy the code
Globals of ESLint adds a $_ configuration
// .eslintrc.js
globals: {
The $_: 'readonly'./ / or true
},
Copy the code
Readonly is configured because we are not overwriting LoDash, just calling its methods.
How to use $_ in Vue
Suppose in A. js. Remove separate lodash and introduce _ : import _ from ‘lodash’ scripts directly using: ‘_ :’ : ‘_. UniqBy (…) The use of ‘template’ can be found below.
Considerations for using templates in Vue
Global variables injected by ProvidePlugin are perfectly fine in Script, but there are minor issues when used in template.
For example:
<p>{{$_ (...). }</p>
Copy the code
data() {
return{$_.}}Copy the code
What is the reason for this? The template syntax of Vue does not support custom data attributes that start with $or _. This is to avoid internal conflicts with Vue.
[Vue warn]:
Property "The $_" must be accessed with "$data.$_".
Because properties starting with "$" or "_" are not proxied in the Vue instance to prevent conflicts with Vue internals
Copy the code
There are several ways to solve this problem:
- through
$data.$_
access - Data is renamed and bound
- Binding in Methods (most recommended)
through$data.$_
access
<p>{{$data.$_(...) }</p>
Copy the code
Data is renamed and bound
<p>{{globalLodash(...) }</p>
Copy the code
data() {
return {
globalLodash: $_.}}Copy the code
Binding in Methods (most recommended)
<p>{{$_ (...). }</p>
Copy the code
methods: {
$_
}
Copy the code
Why is this the most recommended?
This is because the ProvidePlugin finally returns to us a hooks function.
hooks () {
return hookCallback.apply(null.arguments);
}
Copy the code
If it’s a function, it’s actually a method. Since it needs to be used in the Vue template, it needs to be mounted to the Vue instance. So bind directly in Methods and mount to the Vue sample.
So why not mount it on data?
Avoid unnecessary extra expenses. This is because data is used to define reactive data. Our $_ function is just a utility function. There is no two-way binding to it, so it does not need to be defined in data.
thinking
What is the injected ProvidePlugin?
Is a hooks function.
hooks () {
return hookCallback.apply(null.arguments);
}
Copy the code
Will the ProvidePlugin reduce the packaging volume over time?
Don’t. Instead, it will be slightly larger, 0.0X KB. This is my own conclusion when comparing the size of packaged files before and after using ProvidePlugin.
What are the considerations when using ProvidePlugin?
These considerations are mostly for code readability and maintainability.
- Try to define global variables that are as unique as possible, such as _, moment
- Members of the same front-end team are introduced as global variables
- It is best to maintain a global variable document, with special emphasis on new hires
Vue.prototype. XXX and import and require are there more elegant implementations? “That’s it.
Try the ProvidePlugin in your project
I am looking forward to communicating with you and making progress together. Welcome to join the technical discussion group I created which is closely related to front-end development:
- SegmentFault column: Be a good front-end engineer while you’re still young
- Zhihu column: Be an excellent front-end engineer while you are still young
- Github blog: Personal blog 233 while You’re Still Young
- excellent_developers
Strive to be an excellent front-end engineer!