9102: Handwriting a Vue Scaffold [Extreme Optimization Version]

  css, html, html5, javascript, webpack

图片描述

Before reading this article, I suggest you take a look at the following two articles and give a compliment by the way.githubThe praise oh ~

  • If you are rightwebpackNot very understanding, please pay attention to my previous articles, are more than 100 starsstarThe quality of the article

    • 9102: Handwriting a React Perfect Mobile Scaffold
    • Incomplete Manual for Front End Performance Optimization
    • GIT warehouse address
    • Welcome to pay attention to me"Advanced Front End"Column Breakthrough Study Together
    • The content of the article will be updated from time to time and must be collected.
    • This article was written on May 17, 2019. The latest version 4.31 shall not be reproduced without the permission of the author.webpack
    • webpackIt’s addictive, and it’s also a good way to break through your technical bottleneck. Now basically everything is inseparable from it.webpack,webpackWell used, whatnext nuxtI am familiar with it (I know it very well) and I referred to it.VueScaffolding, Jingdong’swebpackThe optimization plan, as well as other aspects of my optimization, focuses onProduction modeThe optimization and improvement of the construction speed under is very obvious (of course, it is also ~) in the development environment, and the performance improvement is very obvious ~
    • This configuration completes the functions:
    • Recognition.VueDocuments andTemplate template
    • tree shakingShake tree optimization to remove useless code
    • introducebabel polifillAnd load on demand, identify all codes
    • Recognitionasync / awaitAnd arrow functions
    • PWAFunction, hot refresh, take over the browser immediately after installation, still allow websites to be accessed and add websites to the desktop on the mobile phone.
    • preloadPreload resourcesprefetchRequest resources on demand, except herednsIn addition to pre-parsing, it is recommended that other components be loaded on demand, and code division is also required. This is also JD.com’s optimization plan.
    • ConfigurationnginxTo intercept unexpected requests (JD.com’s plan)
    • CSSModular, not afraid of naming conflicts
    • Small picturebase64To deal with
    • Save j for file suffixsx js jsonWait
    • RealizationVueRouterLazy loading of routes, loading on demand, code division specifies that multiple routes are the samechunkNameAnd packed into the samechunkTo Achieve Accurate Code Segmentation in
    • Supportless sass stylusEqual pretreatment
    • code splitingOptimize the loading time of the first screen to prevent a file from being too large.
    • Extract common codes and package them into a chunk
    • Each chunk has a correspondingchunkhashEach file has a correspondingcontenthashTo make it easier for browsers to distinguish between caches
    • Picture compression
    • CSSCompression
    • IncreaseCSSPrefix compatible with various browsers
    • Under the specified folder for packaging and outputting various files
    • Cache babel’s compilation results to speed up compilation
    • Each entry file corresponds to a chunk, and after it is packaged, it corresponds to a file as well.code spliting
    • Delete useless contents such as comments of HTML files
    • Delete the old packaged code for each compilation.
    • willCSSThe files are extracted separately.
    • Babel not only caches the compilation results, but also starts multi-thread compilation after the first compilation, which greatly accelerates the construction speed.

There is no end to performance optimization. I only express my current knowledge points. After three days of study, I am impressed.Technology advances every three days.

Let’s start officially, assuming you already know what it is.entry output loader plugin, if you don’t understand, look at my article above oh ~

Webpack common configuration

//Entry File
entry: {
app: './src/js/index.js',
},
//Output File
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
PublicPath: '/' // Ensure that file resources can be accessed correctly at http://localhost:3000
},
//developer tool source-map
devtool: 'inline-source-map',
//Create Developer Server
devServer: {
contentBase: './dist',
Hot: true // hot update
},
plugins: [
//delete dist directory
new CleanWebpackPlugin(['dist']),
//Re-wear html file
new HtmlWebpackPlugin({
title: 'Output Management'
}),
//to make it easier to view dependencies to patch
new webpack.NamedModulesPlugin(),
//Hot Update Module
new webpack.HotModuleReplacementPlugin()
],
//environment
mode: "development",
// loader configuration
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
]
}

Here we focus onmoduleAndpluginsProperty, because today’s focus is on writingloaderAndplugin, these two attributes need to be configured.

  • webpackAfter startup, the configuration will be read first.new MyPlugin(options)Initialize aMyPluginGet an example of it. At initializationcompilerObject, then call themyPlugin.apply(compiler)Incoming to plug-in instancecompilerObject.

Plug-in instance getscompilerObject, you can pass thecompiler.plugin(Event Name, Callback Function) ListenedWebpackA broadcast event.
And you can operate the webpack through the compiler object.

  • CompilerThe object containsWebpackAll configuration information of the environment, includingoptions,loaders,pluginsThis information, this object inWebpackIt is instantiated at startup, it is globally unique, and can be simply understood asWebpackExamples;

    • CompilationYesLike contains the current module resources, compiled resources, changed files, etc. When the Webpack is running in development mode, whenever a file change is detected, a newCompilationWill be created.CompilationObject also provides many event callbacks for plug-ins to extend. viaCompilationCan also be readCompiler`object.
    • Compiler and CompilationThe difference lies in:
    • CompilerOn behalf of the wholeWebpackLife cycle from startup to shutdown, whileCompilationIt just represents a new compilation.
    • Event flow
    • webpackviaTapableTo organize this complex production line.
    • webpackThe event flow mechanism of ensures the order of plug-ins and makes the whole system extensible.
    • webpackThe event flow mechanism of applies observer mode, andEventEmitter in Node.jsVery similar.

1.2 Packaging Principle

  • Identify entry file
  • Module dependencies are identified layer by layer. (Commonjs、amdOr ..es6Theimport,webpackWill analyze it. To obtain code dependencies)
  • webpackWhat you do is analyze the code. Convert code, compile code, output code
  • Finally, the packaged code is formed.
  • These are all.webpackSome basic knowledge of webpack is helpful to understand the working mechanism of WebPack.

Scaffolding is generally followedcommonjsModular scheme, if you don’t understand it very well, then it looks very difficult. The scaffold I wrote will not use modular scheme. It is simple.CoarseStorm

  • Start developing environment configuration
  • Package Manager UsageyarnUse it without explanation.yarn
  • Configurationwebpack.dev.jsConfiguration in Development Mode
  • yarn init -y
  • yarn add webpack webpack-cli(yarnWill automatically add dependencies online or in the development environment)

Configuration portal

entry: path.resolve(__dirname, '../src/main.js')}

Configure output directory

output: {
filename: 'js/[name].[hash:5].js',
path: path.resolve(__dirname, '../dist'),

},

introduceVueBasic configuration in scaffoldloaderAfterloaderIt’s all goingrulesAdd to the array ~

module: {
rules: [
{
test: /\.(png|jpe?  g|gif|svg)(\?  .*)?  $/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name]-[hash:5].[ext]',
}
}
]
},
{
test: /\.(woff2?  |eot|ttf|otf)(\?  .*)?  $/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name]-[hash:5].[ext]',
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?  .*)?  $/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
name: 'media/[name]-[hash:5].[ext]',
}
}
]
}
]
},

Some people will ask so many questions. What do I think? Don’t worry, firsturl-loaderYes processingbase64Picture of, let belowlimitFiles of size tobase64Form use, the latter two same routines, just changed the file type, if not, first copy the past run?

Configuration identification.vueDocuments andtempalteTemplate,yarn add vue vue-loader vue-template-compiler

Add loader

{
test:/\.vue$/,
loader:"vue-loader"
}

Join plugin
const vueplugin = require('vue-loader/lib/plugin')


In plugin of webpack

New vuepugin () is all you need.

Entry designationbabel-polifill,vendorThe code is divided into common modules, and after being packaged, these codes will all be in a common module.

app: ['babel-polyfill', './src/index.js', './src/pages/home/index.js', './src/pages/home/categorys/index.jsx'],
 vendor: ['vuex', 'better-scroll', 'mint-ui', 'element-ui']

appointhtmlThe file is packaged and output by the template, and is automatically imported into the packaged file.jsFile

const HtmlWebpackPlugin = require('html-webpack-plugin');
 
 plugins: [
 new HtmlWebpackPlugin({
 template: path.resolve(__dirname,'../index.html'),
 filename: 'index.html'
 }),
 ]

spare.vueThe suffix of, directly configured inmodule.exportsObject, withentryAt the same level

resolve: {
 extensions: ['.js','.json','.vue'],
 
 }

Add identificationhtmldocumentaryloader

{
 test: /\.(html)$/,
 loader: 'html-loader'
 }

Turn on multi-thread compilation

const os = require('os')
{
loader: 'thread-loader',
options: {
workers: os.cpus().length
}
}

joinbabel-loaderAdd babel-loader and babel preset to parse JSX ES6 syntax

@babel/preset-env Parses es6 Syntax
@ Babel/Plugin-SYNTAX-DYNAMIC-import Resolves vue's IMPORT Load on Demand with CodeSplitting

{
loader: 'babel-loader',
Options: {//jsx syntax
presets: ["@babel/preset-react",
//tree shaking loads babel-polifill on demand
["@babel/preset-env", { "modules": false, "useBuiltIns": "false", "corejs": 2 }]],
plugins: [
//Support import Lazy Loading
"@babel/plugin-syntax-dynamic-import",
//andt-mobile Loading on Demand true is less, and' css' can be written if the value of less style is not used.
["import", { libraryName: "antd-mobile", style: true }],
//Identify class Components
["@babel/plugin-proposal-class-properties", { "loose": true }],
],
cacheDirectory: true
},
}

In using the abovebabelAfter configuration, we can use it lying down.vueRouterThe route of is lazily loaded

Lazy loading of routes

  • When packaging and building applications, JavaScript packages become very large, affecting page loading. If we can divide the components corresponding to different routes into different code blocks and then load the corresponding components when the routes are accessed, it will be more efficient.
  • Combining Vue’s asynchronous component and Webpack’s code division function, lazy loading of routing components is easily realized.
  • First, an asynchronous component can be defined as a factory function that returns a Promise (the Promise returned by this function should resolve the component itself):
  • const Foo = () => Promise.resolve({ /Component definition object/ })
  • Second, in the Webpack, we can use dynamic import syntax to define a code split point:

    • Import('./Foo.vue') // return Promise

pay attention to

  • If you are using Babel, you will need to add the syntax-dynamic-import plug-in to enable Babel to parse the syntax correctly.
  • Combining the two, this is how to define an asynchronous component that can be automatically code-partitioned by the Webpack.
const Foo = () => import('./Foo.vue')

There is no need to change anything in the routing configuration, just use Foo as usual:

const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
# Press the components into blocks

Sometimes we want to package all components under a certain route in the same asynchronous chunk.  Just use the named chunk, a special annotation syntax to provide chunk name (Webpack > 2.4 is required).

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

The Webpack combines any asynchronous module with the same block name into the same asynchronous block.

Add plug-ins hot update plugin and html-webpack-plugin

const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new webpack.HotModuleReplacementPlugin(),


devServer: {
contentBase: '../build',
open: true,
port: 5000,
hot: true
},

joinless-cssIdentified module

{
test: /\.(less|css)$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader'
, options: {
Modules: false, // It is not recommended to turn on css modularization. Some ui component libraries may fail to load on demand.
localIdentName: '[local]--[hash:base64:5]'
}
},
{
loader: 'less-loader',
options: { javascriptEnabled: true }
}
]
},

The following is the official start of the production environment

Stepping on a pit is a good thing. Why don’t you put in the complete source code this time, because stepping on a pit will never improve the technology

htmlKill invalid code

new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
}
}),

Adding picture compression performance optimization is very big

{
 test: /\.(jpg|jpeg|bmp|svg|png|webp|gif)$/,
 
 use:[
 {loader: 'url-loader',
 options: {
 limit: 8 * 1024,
 name: '[name].[hash:8].[ext]',
 outputPath:'/img'
 }},
 {
 loader: 'img-loader',
 options: {
 plugins: [
 require('imagemin-gifsicle')({
 interlaced: false
 }),
 require('imagemin-mozjpeg')({
 progressive: true,
 arithmetic: false
 }),
 require('imagemin-pngquant')({
 floyd: 0.5,
 speed: 2
 }),
 require('imagemin-svgo')({
 plugins: [
 { removeTitle: true },
 { convertPathData: false }
 ]
 })
 ]
 }
 }
 ]
 
 
 
 }

Add file-loader to package and output some files to a fixed directory.

{
 exclude: /\.(js|json|less|css|jsx)$/,
 loader: 'file-loader',
 options: {
 outputPath: 'media/',
 name: '[name].[contenthash:8].[ext]'
 }
 }

Add plug-ins that compress css

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
new OptimizeCssAssetsWebpackPlugin({
cssProcessPluginOptions:{
preset:['default',{discardComments: {removeAll:true} }]
}
}),

Add codesplitting code splitingvueScaffolding is cut separately synchronously and asynchronously. I cut directly together.

optimization: {
 RuntimeChunk:true, // set to true, a chunk is a file after it is packaged, and a chunk corresponds to' some js css pictures', etc.
 splitChunks: {
 Chunks: 'all' // the default entry's chunk will not be split. if it is configured as all, it will be split. an entry' JS',
 //After packaging, a separate file will be generated.
 }
 }

Add plug-in to WorkboxPlugin, PWA

Pwa is a technology that needs to be put into practice. It has its life cycle and the side effects of hot updates in browsers. It needs to be carefully studied.  You can refer to Baidu's lavas framework development history ~
 const WorkboxPlugin = require('workbox-webpack-plugin')
 
 
 new WorkboxPlugin.GenerateSW({
 Clients claim: true//let the browser be taken over immediately.
 Skipwaiting: true//jump the queue to the front immediately after updating the sw file.
 importWorkboxFrom: 'local',
 include: [/\.js$/, /\.css$/, /\.html$/,/\.jpg/,/\.jpeg/,/\.svg/,/\.webp/,/\.png/],
 }),

Optimization Core of Single Page Application:

  • The most important thing is that the route is lazy to load code division.
  • Part of the rendering is completed on the server side, greatly accelerating the rendering speed of the first screen.VUEPreferrednuxtFrame, also can use its scaffolding
  • Picture compression and picture lazy loading are one of the biggest optimizations for page level.
  • Continue writing laternext nuxtAndpwaThe use of ~

There are many holes in the process of scaffold construction, but it can greatly improve your technical ceiling. Follow the author to step on the holes, and don’t forget to come to mine.githubSome praise ~Source code address of warehouse ~ welcome star