WebPack优化

 
  

1 常用的loader和plugin

1.    file-loader加载文件,url-loader也可以加载文件但是当文件小于阙值转为base64返回,url-loader封装了file-loader

  1. css-loader处理css文件、style-loader将css代码以style标签注入到html文件中,less-loader转less文件为css文件

  2. postCss-loader转换css文件,例如添加前缀,转换单位

  3. babel-loader转es6为es5,转换react语法

  4. vue-loader处理vue文件

  5. eslint-loader检查代码规范

  6. devServer 配置服务器webpack-dev-server开发环境静态服务器(属性host、port、proxy、contentbase根目录)

  7. devtool配置sourcemap类型

2 WebPack多入口配置:

  1. entry需要多入口配置,{chunkname: filePath/file.js}

WebPack优化_第1张图片

2 out需要动态配置[name].hash.js

WebPack优化_第2张图片

3 htmlwebpackplugin需要生成多个html(属性template,fimename,chunks),配置html要引入的chunks

WebPack优化_第3张图片

如何抽离压缩css文件

在本地的代码中可以用style-loader把CSS文件放到style中,
但是线上必须要把CSS进行抽离,压缩,不然代码体积很大。

不抽离的CSS文件其实是通过js文件写入html的style标签中的 ,这样要执行js才能把css解析出来放入html中,效率很低。

抽离 css 和 less :
注意这里不再使用style-loader,而是使用 MiniCssExtractPlugin.loader 单独拎出来

1. 抽离:使用miniCssExtratPlugin插件,rules中使用miniCssExtratPlugin.loader替换style-loader,plugin中配置MiniCssExtratPlugin

2. 压缩:在webpack optimization属性中配置minmizer,使用optimizeCssAssetsPlugin等工具压缩css文件去除空格和注释

WebPack优化_第4张图片

WebPack优化_第5张图片

webpack5现在一般要使用CssMinimizerPlugin + MiniCssExtractPlugin,之前的optimize-css-assets-webpack-plugin会报错

const path = require("path");
const {merge} = require("webpack-merge");
const common = require("./webpack.common");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const {distPath, srcPath} = require("./path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = merge(common, {
    mode: "production",
    module: {
        rules: [
            {
                test: /\.css$/,
                include: srcPath,
                exclude: /node_modules/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
            },
            {
                test: /\.less$/,
                include: srcPath,
                exclude: /node_modules/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
            }
        ]
    },
    output:{
        path:distPath,
        filename:'bundle.[contenthash:8].js'
    },
    plugins: [
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename:'main.[contenthash:8].css'
        })
    ],
    optimization:{
        minimizer:[
            new CssMinimizerPlugin()
        ]
    }
})

4 webpack如何抽离公共代码和第三方代码

对应 html 中引入哪些 js 可以在 HtmlWebpackPlugin 中的 chunks 中 配置

WebPack优化_第6张图片

在生产的配置中进行公共代码和第三方代码的抽离:
在 optimization 中加 splitChunks

WebPack优化_第7张图片

webpack 5好像 chunks 是按需导入了-慕课网

 5 webpack如何实现异步加载JS (懒加载)

1 懒加载使用 import(文件路径) 函数来实现,返回一个 promise

  import().then(res => res.default)   或者 SetTimeout 

2使用 chunk:
入口中的 HtmlWebpackPlugin 插件

6  module chunk bundle 的区别

module、chunk、bundle的区别

  1. module 一些源代码,没有经过编译的,webpack中一切皆模块

  2. chunk 多模块合成的,如 entry import() splitChunk(下午中间分析部分)

  3. bundle 最终输出的文件

module 是源码,能引用的都是模块,不管是什么类型,css、js、图片等都是模块,都是源码

chunk 是多模块合并成的,中不一定是一个文件,比如 index.js 中还有引入其他的文件 (chunk 是内存中的概念,还没有输出)

bundle 就是最终输出的文件,一个 chunk 对应一个 bundle

7  webpack优化构建速度

Webpack构建速度优化_如何提高webpack的构建速度_gogo2027的博客-CSDN博客

一、构建速度

  1. 优化babel-loader

    开启缓存(开启cacheDirectory)  use:[babel-loader?cacheDirectory],

    include或者exclude明确范围  eg.include:path.resolve(_dirname,'src')

  2. IgnorePlugin

  3. noParse

  4. happyPack

  5. ParallelUglifyPlugin

  6. 自动刷新

  7. 热更新

  8. DllPlugin

1、babel-loader es6转到es5
2、IgnorePlugin 避免哪些 ?
3、noParse不去管哪些?
4、happyPack 多进程打包
5、parallelUglifyPlugin 开启多进程代码压缩
6、自动刷新
7、热更新-浏览器不用刷新代码生效
8、DllPlugin 第三方或者其他比较大的库事先打包好,作为引用,不用每次重新打包,

  1. 优化babel-loader开启缓存use:[babel-loader?cacheDirectory],es6代码没有改动直接使用缓存不再编译,指定打包范围缩小要处理的文件数量(include/exclude)

  2. WebPack优化_第8张图片

 ignorePlugin避免引入无用模块(不引入,可以手动按需引入)

    忽略moment下的/loacle目录, new webpackPlugin(/\.\/locale/,/moment/)

    业务代码中动态引入需要的语言包,import 'moment/locale/zh-cn'

WebPack优化_第9张图片

 3 noParse避免重复打包(引入,不打包) 已经是压缩过的代码最小的代码

WebPack优化_第10张图片

区别:
IgnorePlugin 直接不引入,代码中没有(自己按需要来引入需要的部分)
noParse 引入,但不打包

4 happyPack多进程打包

  1. JS单线程,开启多进程打包

  2. 提高构建速度(特别是多核CPU)

WebPack优化_第11张图片

5 ParallelUglifyPlugin 多进程压缩JS

  1. webpack内置Uglify工具压缩js

  2. JS单线程,开启多进程压缩更快

  3. 和happyPack同理

关于开启多进程

  1. 项目较大,打包较慢,开启多进程能提高速度

  2. 项目较小,打包很快,开启多进程会降低速度(进程开销)

  3. 按需使用

ParallelUglifyPlugin 的配置直接在 plugins 中 new 就可以,
new 的时候要给 uglifyJS 传一些配置

WebPack优化_第12张图片

 6  配置热更新

自动刷新:

WebPack优化_第13张图片

一般情况下,如果项目引入了devServer,那么就会默认把热更新这个功能开启

 热更新:

WebPack优化_第14张图片

 WebPack优化_第15张图片

WebPack优化_第16张图片

 WebPack优化_第17张图片

热更新是有成本的,要在开发环境下自己注册哪些模块使用热更新

这里注册的范围是 math.js 文件中的内容使用热更新,回调函数部分是热更新之后执行的

在devServer里面配置 hot:true

 
  

7  Dllplugin 动态链接库插件

    DllPlugin(仅为了开发频繁打包体验,用于 dev)

  1. 前端框架如vue react , 体积大,构建慢

  2. 较稳定,不常升级版本

  3. 同一个版本只构建一次即可,不用每次重新构建

  4. 一个库一个是索引

hard-source-webpack-plugin

hard-source-webpack-plugin 为模块提供了中间缓存,重复构建时间大约可以减少 80%,但是在 webpack5 中已经内置了模块缓存,不需要再使用此插件

生成dll文件 - Dllplugin

创建一个webpack.dll.js 运行生成dll文件 和mainefest文件

使用dll文件 DllReferencePlugin

index.html中使用dll文件

DllReferencePlugin 指定mainefest文件地址

8 webpack 优化产出代码

 
  
  1. 体积更小

  2. 合理分包,不重复加载

  3. 速度更快,内存使用更少

方案

  1. 小图片base64格式产出,避免网络请求

  2. bundle+contenthash

  3. 懒加载,非核心代码异步加载

  4. 提取公共代码

  5. IgnorePlugin减少代码

  6. 使用CDN加速,cdn前缀

  7. 使用production

  8. Scope Hosting

9 什么是Tree-Shaking

开启 prodution 模式之后,就会自动开启 Tree-Shaking

没有用到的代码,在生产打包的时候删掉就是 tree-shaking

这里的 mult 函数就是没用到的代码,在生产打包时应该删掉

10 ES6 Module和 Commonjs区别

  1. ES6 Module静态引入,编译时引入

  2. CommonJs是动态引入,执行时引入(require可以放在if else里)

  3. 只有ES6 Module才能静态分析,实现tree-shaking

CommonJs动态引入:

WebPack优化_第18张图片

 ES6 Module静态引入:

WebPack优化_第19张图片

 

11什么是 Scope Hosting?

Scope Hosting

  1. 把多个函数(每个模块可能一个函数)的内容,放到一个函数中

  2. 代码体积更小

  3. 创建函数作用域更少

  4. 代码可读性更好

WebPack优化_第20张图片

 

12 babel 

babel 环境搭建和基本配置

WebPack优化_第21张图片

Presets/env代表了很多常用的plugin配置,省去很多plugin的配置

 WebPack优化_第22张图片

 

babel-polyfill是core-js和regenerater的集合

core-js解决不了yield(generate), regenerater

babel7.4后babel-polyfill已经被弃用,推介使用core-js和regenerater

2 babel-polyfill 按需引入

.babelrc:

WebPack优化_第23张图片

 babel-runtime

babel-polyfull会污染全局环境

如何是打包第三方库,会影响用户的环境

babel-runtime    : 防止babel-polyfill污染全局环境Promise等新特性取一个别名如)_promise。需要在.babelrc presets中配置

  1. babel/runtime

  2. babel/plugin-transform-runtime

WebPack优化_第24张图片

 

 
  

前端为何要进行打包和构建?

体积更小(Tree-Shaking、压缩、合并),加载更快

编译高级语言或语法(TS、ES6+、模块化、scss)

兼容性和错误检查(Polyfill、postcss、eslint)

统一、高效的开发环境

统一的构建流程和产出标准

集成公司构建规范(提测、上线等)

module chunk bundle的区别

module-各个源码文件,webpack中一切皆模块

chunk-多模块合并成的,如entry import()splitChunk

bundle-最终的输出文件

loader和plugin的区别

loader模块转换器,如less->css

plugin扩展插件,如HtmlWebpackPlugin

常见的loader和plugin有哪些

 
  

babel和webpack的区别

babel-JS新语法编译工具,不关心模块化

webpack-打包构建工具,是多个loader plugin的集合

如何产出一个lib(第三方的类)

参考webpack.dll.js

output.library

babel-polyfill和babel-runtime的区别

babel-polyfill会污染全局

babel-runtime不会污染全局

产出第三方lib要用babel-runtime

webpack如何实现懒加载

import()

结合Vue React异步组件

结合Vue-router React-router 异步加载路由

为何Proxy不能被Profill?

如Class可以用function模拟

如Promise可以用callback来模拟

但Proxy的功能用Object.defineProperty无法模拟

没有任何能力能完全模拟出Proxy

Polyfill

Polyfill或者Polyfiller,是英国Web开发者 Remy Sharp 在咖啡店蹲坑的时候拍脑袋造出来的。当时他想用一个词来形容"用JavaScript(或者Flash之类的什么鬼)来实现一些浏览器不支持的原生API"。Shim这个已经有的词汇第一时间出现在他的脑海里。但是他回头想了一下Shim一般有自己的API,而不是单纯实现原生不支持的API。苦思冥想一直想不到合适的单词,于是他一怒之下造了一个单词Polyfill。除了他自己用这个词以外,他还给其他开发者用。随着他在各种Web会议演讲和他写的书《Introducing HTML5》中频繁提到这个词,大家用了都觉得很好,就一起来用。

Polyfill的准确意思为:用于实现浏览器并不支持的原生API的代码。

例如,querySelectorAll是很多现代浏览器都支持的原生Web API,但是有些古老的浏览器并不支持,那么假设有人写了库,只要用了这个库, 你就可以在古老的浏览器里面使用document.querySelectorAll,使用方法跟现代浏览器原生API无异。那么这个库就可以称为Polyfill或者Polyfiller。
好,那么问题就来了。jQuery是不是一个Polyfill?答案是No。因为它并不是实现一些标准的原生API,而是封装了自己API。一个Polyfill是抹平新老浏览器 标准原生API 之间的差距的一种封装,而不是实现自己的API。
已有的一些Polyfill,如 Polymer 是让旧的浏览器也能用上 HTML5 Web Component 的一个Polyfill。FlashCanvas是用Flash实现的可以让不支持Canvas API的浏览器也能用上Canvas的Polyfill。

分割线

---------------------------------------------------------------------------------------------------------------------------------

分割线

Webpack构建速度优化

  • 缩小范围
  • noParse
  • IgnorePlugin
  • 优化 resolve 配置
  • externals
  • 缓存

1  缩小范围

在配置 loader 的时候,我们需要更精确的去指定 loader 的作用目录或者需要排除的目录,通过使用 include 和 exclude 两个配置项,可以实现这个功能,常见的例如:

include:符合条件的模块进行解析
exclude:排除符合条件的模块,不解析,优先级更高
这样一来,一开始构建,我们就能去除一些选项,比如,在使用babel-loader的时候
 

{
  test: /\.jsx?$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env', '@babel/react'],
        plugins: [[require('@babel/plugin-proposal-decorators'), { legacy: true }]],
        cacheDirectory: true, // 启用缓存
      },
    },
  ],
  include: path.resolve(__dirname, 'src'),
  exclude: /node_modules/,
 },

2 noParse

对于我们引入的一些第三方包,比如jQuery,在这些包内部是肯定不会依赖别的包,所以根本不需要webpack去解析它内部的依赖关系,使用 noParse 进行忽略的模块文件中不会解析 importrequire 等语法

module:{
    noParse:/jquery|lodash/
}

3 IgnorePlugin

有很多的第三方包内部会做国际化处理,包含很多的语言包,而这些语言包对我们来说时没有多大用处的,只会增大包的体积,我们完全可以忽略掉这些语言包,从而提高构建效率,减小包的体积。

  • requestRegExp 表示要忽略的路径。
  • contextRegExp 表示要忽略的文件夹目录。
new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });

//以moment为例,首先找到moment中语言包所在的文件夹,然后在webpack配置文件中添加插件
new webpack.IgnorePlugin(/./locale/, /moment/)

这时候moment使用默认语言英语,如果要使用别的语言,可以手动引入需要使用的语言包。

import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-CN')

 4 优化 resolve 配置

alias

alias 用的创建 import 或 require 的别名,用来简化模块引用,项目中基本都需要进行配置。

const path = require('path')
{
  ...
  resolve:{
    // 配置别名
    alias: {
      '~': resolve('src'),
      '@': resolve('src'),
      'components': resolve('src/components'),
    }
  }
}

配置完成之后,我们在项目中就可以

// 使用 src 别名 ~ 
import '~/fonts/iconfont.css'

// 使用 src 别名 @ 
import '@/fonts/iconfont.css'

配合上noParse,在使用的时候,就无须在构建一遍react

你可能感兴趣的:(Vue3.0X,webpack,前端,node.js)