First, we need to know what to pack with WebPack, and what benefits it has. We can simply list the following points:
- Single-file component (.vue file)
- Optimize the Vue build process (alias, etc.)
- Browser Cache Management
- Code separation (lazy loading, etc.)
This article focuses on webpack optimization browser cache management, vuE-CLI generated scaffolding configuration, has done a lot of packaging, the use of cache optimization, this article will school knowledge, and make changes.
Understand browser caching
Before we do that, we need to understand how the browser cache works, so here’s a graph.
- Browser: I need test.js
- Server: Here it is, and don’t come to me for 259,200 seconds (one month)
- Browser: Ok, I’ll cache it to disk
A week later, visit this page again
- Browser: I need test.js, cache life is still in, read directly from disk
- Server: There’s nothing wrong with me
- User: Wow that opens the page quickly
An icon was changed at the request of the product manager
- Browser: I need test.js, cache life is still in, read directly from disk
- Product Manager: Has it been released yet? Are you sure? Why didn’t it work?
- Server: Eat melon
Once we understand how this works, we know how to break the caching mechanism and get the browser to request new files.
Clear cache technique
CTRL +F5 to refresh the page forcibly
Manual forced page refresh, but the users are not programmers, how can they know that forced page refresh is required, so this solution is definitely not feasible for users.
Change the file
- Change the file name: test.js -> test.v2.js
- Change the file path: /static/test.js -> /static/v2/test.js
- Add query string: test.js -> test.js? v=qwer
Now that we know how to clean up caching, how to configure it in the VUe-CLI template
Code Splitting
What is code splitting
We directly generated a new vuE-CLI project, installed the dependencies directly after running the NPM run build command, and opened the /dist/js file directory
It turns out that there are three JS files, and this is where Webpack splits the code.
Why code split
- Separate business code from third-party libraries
- Load on demand (using import() syntax)
The reason why business code and third-party library code are separated is that the product manager’s demand is endless, so the business code updates frequently, on the contrary, the third-party library code update iteration is relatively slow and can lock the version, so the browser cache can be fully used to load these third-party libraries.
For example, load components when accessing a route. Users may not access all routes. Therefore, it is not necessary to load components corresponding to all routes at the beginning. A more typical example is “some users have permissions to access only certain pages”, so there’s no need to load code for pages they don’t have permissions to access
Webpack Code Splitting for VUE-CLI
Separate business code from third-party libraries
Vue-cli uses the CommonsChunkPlugin webpack plug-in to extract framework code. Open the webpack.prod.conf.js file and find the following code
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'.minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '.. /node_modules'= = =))0)}}),Copy the code
This code extracts modules under node_modules with names ending in.js and not duplicates into Vender when packaged.
So the package should generate app.js(business code), vender.js(framework code) two files, careful students may find manifest.js, we will explain later.
Load on demand (using import() syntax)
If we change the loading method of The Hello component to route lazy loading (import() syntax), we are packing
// import Hello from '@/components/Hello'
export default new Router({
routes: [{path: '/'.name: 'Hello'.// component: Hello,
component: () = > import('@/components/Hello')}]})Copy the code
It is obvious that there are four JS files after packaging. Careful students also find that the size of the app.js file plus the size of the extra files is exactly equal to the size of the app without splitting and packaging. In this way, the components equal to asynchronous loading are separately packaged into a JS. When the page is loaded for the first time, it is not necessary to load it. When the corresponding page is requested, it is requested to the server, which reduces the loading time of the first screen of the page.
The output. ChunkFilename configuration in vue-cli /webpack.prod.conf.js specifies the format for packaging asynchronous files
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')},Copy the code
How to exploit the browser cache
The target
Suppose we now have many, many static files and need to update many, many files at a time. Would we manually change the names of the files one by one? The ideal, of course, is to automatically generate a new file name whenever a file is updated.
On the other hand, if we pack a static file with a single JavaScript file app.js, the app.js file name will definitely change every time we change the code. But the fact that I changed the code of one module (and not the other modules) and broke the cache of the other modules is obviously a poor use of the cache. Our goals are:
Which module updates that break its cache, and which module does not update continues to exploit the cache.
Step 1: Add the hash value
We mentioned three ways to clean the cache: change the file name, change the path, and add parameters to the URL. Webpack does this by changing the file name. Output. chunkFilename in vue-cli /webpack.prod.conf.js specifies the format for packaging asynchronous files
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
// Specify the file name as chunk.name.hash.js in the js folder
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
// Specify a file named module id.hash.js in the js folder
},
Copy the code
So if you hash each file, that file changes and the hash value changes
Step 2: Extract the Manifast file
Why extract the manifast file?
The reason is that Vendor Chunk contains the Runtime code for WebPack (runtime code for parsing and loading modules and so on)
The result: even if you don’t change the import module (if vendor’s module doesn’t change, you just change the rest of the code), vendor’s chunkhash value will change, breaking the cache and failing to achieve the desired effect
Vue-cli /webpack.prod.conf.js Extract the manifast
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest'.minChunks: Infinity
}),
Copy the code
Step 3: Generate a four-digit hash for the module ID based on the relative path of the module
Each module in webpack has a Module ID. The Module ID is the sequential number assigned to the module in the module dependency diagram. If the Module ID changes, its chunkhash will also change.
This will result in: if you introduce a new module, the module ID will change as a whole, and possibly the chunkhash of all files will change, which is obviously not what we want
You need to use HashedModuleIdsPlugin to generate a four-digit hash for the module ID based on the relative path of the module, so that if a new module is introduced, the module ID value will not be affected, as long as the module path remains unchanged.
vue-cli /webpack.prod.conf.js
new webpack.HashedModuleIdsPlugin()
Copy the code
Meet the target
So far, if we change the code of one module, it will not break the cache of other modules. This is the persistence cache we want to implement.
Upgrade webpack in VUe-CLI to improve the loading speed of the home page
Analysis of the
Let’s start with an actual project
Run NPM Run build –report to see the packaging distribution mapWe found that the biggest file is vendor, where most of the framework code is packaged, and the framework code does not change often and does not need to be packaged every time. So we can find a way to extract them and hang them on the CDN.
Specific steps
Take VUE, VUe-Router, and Element-UI as examples
Step 1 Index. HTML CDN import framework
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8">
<title>demo-vue-project</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.8/theme-chalk/index.css">
</head>
<body>
<div id="app"></div>
<! -- built files will be auto injected -->
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/element-ui/2.0.7/index.js"></script>
</body>
</html>
Copy the code
Step 2 change the build/webpack. Base. Conf. Js
module.exports = {
...
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'element-ui': 'ELEMENT'
},
...
}
Copy the code
Step 3 Change the framework registration mode
Modify the SRC/router/index. Js
// import Vue from 'vue'
import VueRouter from 'vue-router'
/ / comment out
// Vue.use(VueRouter).Copy the code
Modify the SRC/main. Js
import Vue from 'vue'
import App from './App'
import router from './router'
import ELEMENT from 'element-ui'
// import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
Vue.use(ELEMENT)
Vue.prototype.$http = axios
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
template: '<App/>'.components: { App }
})
Copy the code
packaging
After packaging, we found that vendor was much smaller because the library code was loaded with CDN. However, this will lead to increased request resources and a cost of response, which is only one idea. The final solution to the first screen problem is SSR
conclusion
Now you have some knowledge of the package configuration in VUe-CLI. Personal quip webpack is really complicated. Wait and see what Parcel can do for a different experience.