webpack5

基本使用

webpack 是一个静态资源打包工具
它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。输出的文件就是编译好的文件,就可以在浏览器段运行了我们将 Webpack 输出的文件叫做 bundle 。

功能介绍

Webpack 本身功能是有限的:

  • 开发模式:仅能编译 JS 中的 ES Module 语法
  • 生产模式: 能编译 JS 中的 ES Module 语法,还能压缩 JS 代码

目标

webpack 本身功能比较少,只能处理 js 资源,一旦遇到 css 等其他资源就会报错 。
学习 webpack 主要是学习如何处理其他资源

webpack 核心概念

  1. 入口(entry)
    指示 Webpack 从哪个文件开始打包
  2. 输出(output)
    指示 Webpack 打包完的文件输出到哪里去,如何命名等
  3. loader
    webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析
  4. 插件(plugins)
    扩展 Webpack 的功能
  5. 模式(mode)
    • 开发模式:development
    • 生产模式:production

安装

npm init -y
npm i webpack webpack-cli -D

配置

在文件根目录新建 webpack.config.js

const path = require('path'); // nodejs核心模块,专门处理路径问题
// 配置
module.exports = {
    // 入口
    entry: './src/main.js', // 相对路径
    // 输出
    output: {
        // 文件的输出路径
        // __dirname node.js的变量,代表当前文件的文件夹目录
        path: path.resolve(__dirname, 'dist'), // 绝对路径
        // 文件名称
        filename: 'main.js'
    },
    // 加载器
    module: {
        rules: [
            // loader的配置
        ]
    },
    // 插件
    plugins: [
        // plugin的配置
    ],
    // 模式
    mode: 'development'
}

开发模式介绍

开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:

    1. 编译代码,使浏览器能识别运行
      开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源。
    1. 代码质量检查,树立代码规范
      提前检查代码的一些隐患,让代码运行时能更加健壮。
      提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。

处理样式资源

处理 css

  • 下载 style-loader 和 css-loader
npm i style-loader css-loader -D
  • 配置
module: {
    rules: [
        {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
      }
    ]
}

处理 Less

  • 下载 less-loader 和 less
npm i less-loader less -D
  • 配置
module: {
    rules: [
        {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
      }
    ]
}

处理 Sass

  • 下载 sass-loader 和 sass
npm i sass-loader sass -D
  • 配置
module: {
    rules: [
        {
            test: /\.scss$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
      }
    ]
}

处理 stylus

  • 下载 stylus-loader
npm i stylus-loader -D
  • 配置
module: {
    rules: [
        {
            test: /\.styl$/,
            use: ['style-loader', 'css-loader', 'stylus-loader']
      }
    ]
}

处理图片资源

  • webpack4 时,处理图片资源需要通过 file-loader 和 url-loader 进行处理
  • 下载 url-loader 和 file-loader
npm i url-loader file-loader -D
  • 配置
module: {
    rules: [
        {
            test: /\.(jpg|png|gif|bmp|jpeg|webp)$/,
            use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        name: '[hash:10].[ext]',
                        outputPath: 'imgs'
                    }
                }
            ]
      }
    ]
}
  • webpack5 时,这两个 loader 已经内置到 webpack 中,只需要配置 type: 'asset'

  • 配置

module: {
    rules: [
        {
            test: /\.(jpg|png|gif|bmp|jpeg|webp)$/,
            type: 'asset',
            parser: {
                dataUrlCondition: {
                    maxSize: 10 * 1024 // 小于10kb会转base64,(优点:会减少请求数量,缺点:体积会更大)
                }
            }
        }
    ]
}

修改打包输出文件目录

    1. JS 文件的去找 output 配置,并修改其中的 filename
     filename: 'static/js/main.js',
    
    1. 图片的去找图片的 loader,并添加 generator 配置
      generator: {
          filename: 'static/images/[hash:10][ext][query]'
      }
    
    

自动清空上次打包结果

  • 在 output 配置中添加clean: true

处理字体图标资源

  • 在 loader 中配置(和对图片的处理配置一样)
  {
    test: /\.(ttf|woff2?|eot|otf)$/,
    type: 'asset/resource',
    generator: {
        // 生成输出字体图标名称
        filename: 'static/fonts/[hash:10][ext][query]'
    }
}

处理其他资源(音视频等)

  • 在 type 为'asset/resource'配置的 test 匹配规则后面继续增加
  test: /\.(ttf|woff2?|eot|otf|mp3|mp4)$/,

处理 JS 资源

  • 针对 js 兼容性处理,我们使用 Babel 来完成
  • 针对代码格式,我们使用 Eslint 来完成

Eslint

  • 检测代码中潜在的问题和错误的工具,可以配置各项功能

  • 在 webpack4 中是一个 loader,在 webpack5 中是一个 plugin

  • 安装 Eslint

npm i eslint-webpack-plugin eslint -D
  • 在 webpack.config.js 中配置 Eslint 插件
const ESLintWebpackPlugin = require('eslint-webpack-plugin')

module.exports = {
    plugins: [
         new ESLintPlugin({
            context: path.resolve(__dirname, 'src') // 指定检查的目录
        })
    ]
}
  • 在根目录创建.eslintrc.js文件
module.exports = {
    extends: ["eslint:recommended"],
    env: {
        node: true, // 启用node中全局变量
        browser: true // 启用浏览器中全局变量
    },
    parserOptions: {
        ecmaVersion: 6, // es6
        sourceType: "module" // es module
    },
    rules: {
        "no-var": 2, // 不能使用var定义变量
    }
    // ...更多规则看官网

}

Babel

  • 用于将 ES6 代码转换成向后兼容的 JS 语法

  • 安装 Babel

npm i @babel/core @babel/preset-env babel-loader -D
  • 在 webpack.config.js 中配置 Babel
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/, // 不处理node_modules中的js文件
                use: {
                    loader: 'babel-loader'
                }
            }
        ]
    }
}
  • 在根目录创建babel.config.js文件
module.exports = {
    // 智能预设,能够编译es6的语法
    presets: ["@babel/preset-env",]
}

处理 Html 资源

  • 安装 html-webpack-plugin
npm i html-webpack-plugin -D
  • 在 webpack.config.js 中配置 html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
             template: path.resolve(__dirname,'public/index.html') // 指定模板文件路径
            }
        )
    ]
}

开发服务器&自动化

  • 安装 webpack-dev-server
npm i webpack-dev-server -D
  • 在 webpack.config.js 中配置开发服务器
module.exports = {
    devServer: {
        host: 'localhost', // 设置启动时候的主机地址
        port: 3000, // 设置启动时候的运行端口
        open: true // 自动打开浏览器访问
    }
}
  • 启动服务器
npx webpack serve

生产模式介绍

生产模式是开发完成代码后,我们需要得到代码将来部署上线,这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:

    1. 优化代码运行性能
    1. 优化代码打包速度

生产模式准备

    1. 根目录创建 config 文件夹
    1. 在下面创建webpack.dev.jswebpack.prod.js,分别用于开发模式和生产模式下的配置文件,
  • 2.1 开发环境不需要输出,所以设置 path: undefined
  • 2.2 开发模式下,不需要输出,所以注释 clean: true
  • 2.3 生产模式下,需要输出,所有用到绝对路径的都要用../返回上一层
  • 2.4 生产模式不需要 devServer
  • 2.5 开发模式和生产模式中 mode 要统一

生产模式配置

CSS 处理 (提取 CSS 成单独文件)

  • CSS 文件目前被打包到 JS 中,当 JS 加载时创建 style 标签来生成样式,这会导致页面闪屏,影响用户体验,应该将 CSS 直接提取成单独的样式文件,通过 link 标签引入

  • 安装 mini-css-extract-plugin

npm i mini-css-extract-plugin -D
  • 在 webpack.prod.js 中配置
  • 之前所有写 style-loader 的地方,现在都需要改成 MiniCssExtractPlugin.loader,因为 style-loader 会动态创建 style 标签
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, // 提取成单独文件
                    'css-loader',
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin()
    ],
}

CSS 兼容性处理

  • 安装 postcss-loader postcss postcss-preset-env
npm i postcss-loader postcss postcss-preset-env -D
  • 在 webpack.prod.js 中配置
  • 该配置需要写在 css-loader 的后面和 less-loader、sass-loader 的前面
{
    loader: 'postcss-loader', // 配置postcss
    options: {
        postcssOptions: {
            plugins: [
                postcss-preset-env' // 能解决大多数样式兼容性问题
            ]
        }
    }
},
  • 在 package.json 中配置
  • 指定兼容性处理到哪个浏览器版本
  • 实际开发中可以设置为 "last 2 version" , "> 1%" , "not dead"
  "browserslist": [
    "ie >= 8"
  ]

封装样式 loader 函数

  • 由于上面配置的 CSS 兼容性样式处理代码冗余,将他封装成一个 loader 函数
function getStyleLoader(pre) {
    return [ // 执行顺序,从右到左,从下到上
        MiniCssExtractPlugin.loader, // 将css提取成单独文件
        'css-loader', // 将css编译成commonjs的模块到js中
        {
            loader: 'postcss-loader', // 配置postcss
            options: {
                postcssOptions: {
                    plugins: [
                        'postcss-preset-env' // 能解决大多数样式兼容性问题
                    ]
                }
            }
        },
        pre
    ].filter(Boolean)
}
  • 使用
getStyleLoader()
getStyleLoader('less-loader')
getStyleLoader('sass-loader')
getStyleLoader('stylus-loader')

CSS 压缩

  • 安装插件
npm i css-minimizer-webpack-plugin -D
  • 在 webpack.prod.js 中配置
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

optimization: {
    minimizer: [
        new CssMinimizerPlugin()
    ]
}

HTML 压缩

  • 默认生产模式已经开启了 HTML 和 JS 压缩

webpack 优化

    1. 提升开发体验
    1. 提升打包构建速度
    1. 减少代码体积
    1. 头还代码运行性能

开发体验优化

SourceMap

  • 是一个源代码映射文件, 里面存储了代码转换后的位置信息

  • 实际开发中只需要关注两种情况即可

  • 在 webpack 中配置

    • 开发模式:cheap-module-source-map
    • 优点: 打包速度快
    • 缺点: 没有列映射
module.exports: {
    // ...
    mode:'development',
    devtool:'cheap-module-source-map'
}
  • 在 webpack 中配置
    • 生产模式:source-map
    • 优点: 包含行/ 列映射
    • 缺点: 打包速度慢
module.exports: {
    // ...
    mode:'production',
    devtool:'source-map'
}

提升打包构建速度

Hot Module Replacement

  • 热模块替换, 简称 HMR

  • 作用: 一个模块发生变化, 只会重新打包这一个模块(而不是打包所有模块)

  • CSS 已经由 style-loader 开启 HMR

  • JS 需要手动开启(但实际开发中,会使用 vue-loader 或 react-loader 来解决)

  • 在 webpack 中配置

module.exports: {
    // ...
    devServer: {
        // ...
        // 开启HMR功能(只能用于开发环境)
        // hot默认值:开启
        hot:true
    }
}

OneOf

  • 作用: 防止匹配多个 loader 处理文件
  • 在 webpack 中配置(开发模式和生产模式皆可)
module: {
    rules: [
        {
            // 每个文件只能被其中一个loader配置处理
            oneOf: [
                // ...loader
            ]
        }
    ]
}

Include/Exclude

  • Include: 包含,只处理匹配到的文件
  • Exclude: 排除,不处理匹配到的文件
    • 注意: 只能使用一种,同时使用会报错
 rules: [
     {
        test: /\.js$/,
        // exclude: /node_modules/,
        include: path.resolve(__dirname, '../src'),
        use: { loader: 'babel-loader' }
    }
 ]

Cache

  • 每次打包 JS 文件都要经过 Eslint 检查 和 Babel 编译,速度比较慢。缓存之前的编译结果,第二次打包时速度会变快。
  • 在 webpack.prod.js 中配置
module.exports: {
    module:{
        rules:[
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                use: {
                    loader: 'babel-loader',
                        options: {
                            cacheDirectory: true, // 开启babel缓存
                            cacheCompression: false, // 关闭缓存文件压缩
                    }
                }

            }
        ]
   },
    plugins: [
        new ESLintPlugin({
            context: path.resolve(__dirname, '../src'), // 指定检查的目录
            exclude: 'node_modules', // 排除检查
            cache: true, // 开启缓存
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache') // 指定缓存位置
        }),
    ]
}

Thead

  • 多进程打包:开启电脑的多个进程同时干一件事,速度更快。
  • 注意:请仅在特别耗时的操作中使用,因为每个进程启动就有大约为 600ms 左右开销。
  • 安装
  npm i thread-loader -D
  • 在 webpack 中配置
// 获取cpu核数
const os = require('os')
const threads = os.cpus().length
const TerserPlugin = require("terser-webpack-plugin");

module.exports: {
    module:{
        rules:[
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                use: [
                    {
                        loader: 'thread-loader', // 开启多进程
                        options: {
                            workers: threads, // 进程数量
                        }
                    },
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: true, // 开启babel缓存
                            cacheCompression: false, // 关闭缓存文件压缩
                        }
                    }
                ]

            }
        ]
   },
    plugins: [
        new ESLintPlugin({
            context: path.resolve(__dirname, '../src'), // 指定检查的目录
            exclude: 'node_modules', // 排除检查
            cache: true, // 开启缓存
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcache') // 指定缓存位置
            threads, // 开启多进程和进程数量
        }),
        new TerserPlugin({
            parallel: threads // 开启多进程和进程数量
        })
    ]
}

减少代码体积

Tree Shaking

  • Tree Shaking 是一个术语,通常用于描述移除 JavaScript 中的没有使用上的代码。(例如我们引入了一些函数库,但实际只使用了其中的几个功能,如果将这些都打包进来,那么项目的体积就太大了)

  • 注意:它依赖 ES Module

  • webpack 已经默认开启了这个功能,无需其他配置。

Babel

  • @babel/plugin-transform-runtime: 禁用了 Babel 自动对每个文件的 runtime 注入,而是引入 @babel/plugin-transform-runtime 并且使所有辅助代码从这里引用。

  • 安装

npm i @babel/plugin-transform-runtime -D
  • 在 webpack 中配置
module.exports: {
    module:{
        rules:[
            {
                test: /\.js$/,
                include: path.resolve(__dirname, '../src'),
                use: [
                    {
                        loader: 'thread-loader', // 开启多进程
                        options: {
                            workers: threads, // 进程数量
                        }
                    },
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: true, // 开启babel缓存
                            cacheCompression: false, // 关闭缓存文件压缩
                            plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                        }
                    }
                ]

            }
        ]
   }
}

Image Minimizer

  • 压缩项目本地图片体积

  • 安装

npm i image-minimizer-webpack-plugin imagemin -D
  • 安装无损压缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
  • 安装有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
  • 配置
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); // 无损压缩


module.exports = {
    optimization: {
        minimizer: [
            new CssMinimizerPlugin(),
            new TerserPlugin({
                parallel: threads // 开启多进程和进程数量
            }),
            // 压缩图片
            new ImageMinimizerPlugin({
                minimizer: {
                    implementation: ImageMinimizerPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ]
    },
}

优化代码运行性能

Code Split

  • 打包代码时会将所有 js 文件打包到一个文件中,体积太大了。我们如果只要渲染首页,就应该只加载首页的 js 文件,其他文件不应该加载。

  • 所以我们需要将打包生成的文件进行代码分割,生成多个 js 文件,渲染哪个页面就只加载某个 js 文件,这样加载的资源就少,速度就更快。

  • 代码分割(Code Split)主要做了两件事:

      1. 分割文件:将打包生成的文件进行分割,生成多个 js 文件。
      1. 按需加载:需要哪个文件就加载哪个文件。

需求: 多入口文件之间有公共代码需要处理(多次引用的公共方法打包成一个单独的 JS 文件)

  • 步骤 1
module.exports = {
    // 单入口
    entry: './src/main.js',

    // 多入口
    // 写几个配置就会输出多少js文件
    entry: {
        app: './src/app.js',
        main: './src/main.js',
    },
    // ...
}
  • 步骤 2
  • 通过 optimization.splitChunks 实现,它是一个对象,里面包含很多配置项。
  optimization: {
    // 代码分割配置
    splitChunks: {
      chunks: "all", // 对所有模块都进行分割
      // 以下是默认值
      // minSize: 20000, // 分割代码最小的大小
      // minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
      // minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
      // maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
      // maxInitialRequests: 30, // 入口js文件最大并行请求数量
      // enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
      // cacheGroups: { // 组,哪些模块要打包到一个组
      //   defaultVendors: { // 组名
      //     test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
      //     priority: -10, // 权重(越大越高)
      //     reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
      //   },
      //   default: { // 其他没有写的配置会使用上面的默认值
      //     minChunks: 2, // 这里的minChunks权重更大
      //     priority: -20,
      //     reuseExistingChunk: true,
      //   },
      // },
      // 修改配置
      cacheGroups: {
        // 组,哪些模块要打包到一个组
        // defaultVendors: { // 组名
        //   test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
        //   priority: -10, // 权重(越大越高)
        //   reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
        // },
        default: {
          // 其他没有写的配置会使用上面的默认值
          minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
  • 步骤 3
    • 按需加载,动态导入(加载页面时没有被使用的 JS 不要引入)
    • import 动态导入,会将动态导入的文件代码分割(拆分成单独模块),在需要使用的时候自动加载
// 导入实现累加的方法
import('./add.js')
  .then((res) => {
    console.log('加载成功')
    console.log(res.default(2,3))
  })
  .catch((err) => {
    console.log('加载失败')
  })

需求: 单入口文件之间有公共代码需要处理(多次引用的公共方法打包成一个单独的 JS 文件)

  • 步骤 1
    • 配置 optimization.splitChunks
// 只需要配置这一个就可以(配置方法同上),其他都用默认值
    chunks: "all",
  • 步骤 2
    • 动态导入语法(同上)

动态导入文件更名

  • 步骤 1
// 导入实现累加的方法
import(/* webpackChunkName:"add" */ "./add.js")
  .then((res) => {
    console.log('加载成功')
    console.log(res.default(2,3))
  })
  .catch((err) => {
    console.log('加载失败')
  })
  • 步骤 2
    • 在 webpack 的 output 中配置 filename
output: {
    // ...
    chunkFilename: 'static/js/[name].js'
}

统一命名配置

module.exports = {
    output:{
        // 步骤1
        // 入口文件打包输出文件名
        filename:'static/js/[name].js',
        // 非入口文件打包输出文件名
        chunkFilename:'static/js/[name].chunk.js',
        // 图片、字体等资源文件打包输出文件名
        assetModuleFilename:'static/media/[hash:10][ext][query]'
    },
    plugins:[
        // ...
        new MiniCssExtractPlugin({
          filename:'static/css/[name].css',
          chunkFilename:'static/css/[name].chunk.css'
        })
    ]
}

Preload 和 Prefetch

  • 初始 JS 加载完之后,在没有更多资源需要从服务器获取时,可以使用PreloadPrefetch 来加载更多的将要用到的资源

    • Preload:告诉浏览器立即加载资源。
    • Prefetch:告诉浏览器在空闲时才开始加载资源。
  • 共同点

    • 它们都只会加载资源,不会执行。
    • 都有缓存。
  • 它们区别:

    • Preload加载优先级高,Prefetch加载优先级低。
    • Preload只能加载当前页面需要使用的资源,Prefetch可以加载当前页面资源,也可以加载下一个页面需要使用的资源。
  • 总结:

    • 当前页面优先级高的资源用 Preload 加载。
    • 下一个页面需要使用的资源用 Prefetch 加载。
  • 安装

npm i @vue/preload-webpack-plugin -D
  • 在 webpack 中配置
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");

module.exports = {
    plugins: [
        new PreloadWebpackPlugin({
            // 用preload
            rel: "preload", // preload兼容性更好
            as: "script",

            // 用prefetch
            // rel: 'prefetch' // prefetch兼容性更差
        }),
    ],
}

需求
当我们修改 math.js 文件再重新打包的时候,因为 contenthash 原因,math.js 文件 hash 值发生了变化(这是正常的)。

但是 main.js 文件的 hash 值也发生了变化,这会导致 main.js 的缓存失效。明明我们只修改 math.js, 为什么 main.js 也会变身变化呢?

  • 原因:
    • 更新前:math.xxx.js, main.js 引用的 math.xxx.js
    • 更新后:math.yyy.js, main.js 引用的 math.yyy.js, 文件名发生了变化,间接导致 main.js 也发生了变化
  • 解决:

将 hash 值单独保管在一个 runtime 文件中。

我们最终输出三个文件:main、math、runtime。当 math 文件发送变化,变化的是 math 和 runtime 文件,main 不变。

runtime 文件只保存文件的 hash 值和它们与文件关系,整个文件体积就比较小,所以变化重新请求的代价也小。

  • 配置
module.exports = {
    optimization: {
        minimizer: [
            // ...
        ],
        splitChunks: {
            name: (entrypoint) => `runtime~${entrypoint.name}.js`, // runtime文件命名规则
        }

    },
}

Core.js

  • core-js 是专门用来做 ES6 以及以上 API 的 polyfill

  • polyfill翻译过来叫做垫片/补丁。就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性。

  • 安装

npm i core-js
  • 入口文件引入
// 手动全部引入
import "core-js";

// 手动按需引入(需要什么引入什么)
import "core-js/es/promise";
  • 配置

    • 在根目录创建 babel.config.js
    module.exports = {
      // 智能预设:能够编译ES6语法
      presets: [
        [
          "@babel/preset-env",
          // 按需加载core-js的polyfill
          {
              useBuiltIns: "usage",
              corejs: 3
          },
        ],
      ],
    };
    
    

PWA

需求: 开发 Web App 项目,项目一旦处于网络离线情况,就没法访问了。我们希望给项目提供离线体验。

  • 渐进式网络应用程序(progressive web application - PWA):是一种可以提供类似于 native app(原生应用程序) 体验的 Web App 的技术。

  • 其中最重要的是,在 离线(offline) 时应用程序能够继续运行功能。

  • 内部通过 Service Workers 技术实现的。

  • 安装

npm i workbox-webpack-plugin -D
  • 在 webpack 中配置
const WorkboxPlugin = require("workbox-webpack-plugin");

module.exports = {
    // ...
    plugins: [
        // ...
        new WorkboxPlugin.GenerateSW({
        // 这些选项帮助快速启用 ServiceWorkers
        // 不允许遗留任何“旧的” ServiceWorkers
        clientsClaim: true,
        skipWaiting: true,
        }),
    ]
}
  • 在入口文件中(一般是 main.js)
if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then((registration) => {
        console.log("SW registered: ", registration);
      })
      .catch((registrationError) => {
        console.log("SW registration failed: ", registrationError);
      });
  });
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容