什么是PWA?

PWA,渐进式网络开发应用程序(离线可访问)
workbox => workbox-webpack-plugin
image.png

workbox-webpack-plugin

  1. npm i workbox-webpack-plugin -D

配置文件

  1. const { resolve } = require('path');
  2. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  3. const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
  6. // 定义nodejs环境变量:决定使用browserslist的哪个环境
  7. process.env.NODE_ENV = 'production';
  8. // 复用loader
  9. const commonCssLoader = [
  10. MiniCssExtractPlugin.loader,
  11. 'css-loader',
  12. {
  13. // 还需要在package.json中定义browserslist
  14. loader: 'postcss-loader',
  15. options: {
  16. ident: 'postcss',
  17. plugins: () => [require('postcss-preset-env')()]
  18. }
  19. }
  20. ];
  21. module.exports = {
  22. entry: './src/js/index.js',
  23. output: {
  24. filename: 'js/built.[contenthash:10].js',
  25. path: resolve(__dirname, 'build')
  26. },
  27. module: {
  28. rules: [
  29. {
  30. // 在package.json中eslintConfig --> airbnb
  31. test: /\.js$/,
  32. exclude: /node_modules/,
  33. // 优先执行
  34. enforce: 'pre',
  35. loader: 'eslint-loader',
  36. options: {
  37. fix: true
  38. }
  39. },
  40. {
  41. // 以下loader只会匹配一个
  42. // 注意:不能有两个配置处理同一种类型文件
  43. oneOf: [
  44. {
  45. test: /\.css$/,
  46. use: [...commonCssLoader]
  47. },
  48. {
  49. test: /\.less$/,
  50. use: [...commonCssLoader, 'less-loader']
  51. },
  52. /*
  53. 正常来讲,一个文件只能被一个loader处理。
  54. 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
  55. 先执行eslint 在执行babel
  56. */
  57. {
  58. test: /\.js$/,
  59. exclude: /node_modules/,
  60. loader: 'babel-loader',
  61. options: {
  62. presets: [
  63. [
  64. '@babel/preset-env',
  65. {
  66. useBuiltIns: 'usage',
  67. corejs: { version: 3 },
  68. targets: {
  69. chrome: '60',
  70. firefox: '50'
  71. }
  72. }
  73. ]
  74. ],
  75. // 开启babel缓存
  76. // 第二次构建时,会读取之前的缓存
  77. cacheDirectory: true
  78. }
  79. },
  80. {
  81. test: /\.(jpg|png|gif)/,
  82. loader: 'url-loader',
  83. options: {
  84. limit: 8 * 1024,
  85. name: '[hash:10].[ext]',
  86. outputPath: 'imgs',
  87. esModule: false
  88. }
  89. },
  90. {
  91. test: /\.html$/,
  92. loader: 'html-loader'
  93. },
  94. {
  95. exclude: /\.(js|css|less|html|jpg|png|gif)/,
  96. loader: 'file-loader',
  97. options: {
  98. outputPath: 'media'
  99. }
  100. }
  101. ]
  102. }
  103. ]
  104. },
  105. plugins: [
  106. new MiniCssExtractPlugin({
  107. filename: 'css/built.[contenthash:10].css'
  108. }),
  109. new OptimizeCssAssetsWebpackPlugin(),
  110. new HtmlWebpackPlugin({
  111. template: './src/index.html',
  112. minify: {
  113. collapseWhitespace: true,
  114. removeComments: true
  115. }
  116. }),
  117. new WorkboxWebpackPlugin.GenerateSW({
  118. /**
  119. * 1. 帮助serviceworker快速启动
  120. * 2. 删除旧的 serviceworker
  121. * 作用: 生成一个 serviceworker 配置文件~
  122. */
  123. clientsClaim: true,
  124. skipWaiting: true
  125. })
  126. ],
  127. mode: 'production',
  128. devtool: 'source-map'
  129. };

注册serviceWorker

  • index.js
    /*
    1. eslint不认识 window、navigator全局变量
      解决:需要修改package.json中eslintConfig配置
        "env": {
          "browser": true // 支持浏览器端全局变量
        }
     2. sw代码必须运行在服务器上
        --> nodejs
        -->
          npm i serve -g
          serve -s build 启动服务器,将build目录下所有资源作为静态资源暴露出去
    */
    // 注册serviceWorker
    // 处理兼容性问题
    if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
      navigator.serviceWorker
        .register('/service-worker.js')
        .then(() => {
          console.log('sw注册成功了~');
        })
        .catch(() => {
          console.log('sw注册失败了~');
        });
    });
    }