Webpack学习

Webpack

学习视频: https://www.bilibili.com/video/BV1e7411j7T5?p=1

1. 简介

参考链接: https://segmentfault.com/a/1190000017777256

webpack 是前端的一个项目构建工具,它是基于Node.js开发出来的一个前端工具。WebPack可以看做是模块打包器(module bundler),通过分析项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

在这里插入图片描述
为什么要使用webpack?

  1. JavaScript和CSS的依赖问题。开发过程中,JavaScript和CSS的在页面中的顺序问题,经常会造成CSS没起作用,JavaScript的某个变量和方法找不到。
  2. 性能优化。一般浏览器请求的文件越多越耗时,请求的文件越大越耗时,尤其是为了前端项目的代码更清晰,结构更合理,我们采用了MVC,MVVM等很多架构分解出了很多JS文件,无疑又拖慢了网页的速度。为了解决这个问题,一般会采用以下两个方案:
    (1)、 文件合并。浏览器需要下载多个JS文件,而浏览器是有并发限制,也就是同时并发只能下载几个文件。当需要加载的文件非常多,网页的性能可想而知,所以我们需要合并多个文件以减少文件的数量。
    (2)、 文件压缩。我们知道文件越大,下载越慢,而针对JavaScript和CSS,里面的空格,换行这些都是为了让我们读代码时更容易阅读,但是对机器来说,这些对它没有影响。
  3. 提高开发效率。主要体现在:
    (1)、 Vendor前缀。在CSS3使用越来越多的时候,我们都知道一些CSS3的新特性,在不同的浏览器中,CSS有不同的前缀,如果我们手工添加将会很繁琐,而如果使用构建工具,很多构建工具可以自动给我添加CSS的Vendor前缀。关于vendor前缀的学习
    (2)、单元测试。JavaScript的单元测试在使用MVC或者MVVM的框架后,变得越来越容易,而单元测试是质量保证的一个很重要的手段,所以在提交之前,使用构建工具自动跑一遍我们的单元测试是非常有必要的,能进一步检测你的项目的健壮性和容错能力。关于MVVM的学习
    (3)、代码分析。我们写的JavaScript很多时候会有一些潜在的bug, 比如忘了添加分号,某个变量没有等等,使用一些JavaScript的代码分析工具,可以很好的帮我们检查一些常见的问题。

2. Webpack打包步骤

  1. 首先安装node.js

    官方网址: https://nodejs.org/zh-cn/

  2. 初始化项目

    npm init -y
    
  3. 安装webpackwebpack-cli

    npm install webpack webpack-cli -D
    
  4. 修改webpack.config.js文件

  5. 修改packjson.json

    {
        "name": "webpack_study",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
            "test": "echo \"Error: no test specified\" && exit 1",
            "dev": "webpack --mode development --watch" // 加上这一行
            // --watch 实时监听, 如有改动立刻重新打包
        },
        "keywords": [],
        "author": "",
        "license": "ISC",
        "devDependencies": {
            "@babel/core": "^7.2.2",
            "@babel/preset-env": "^7.3.1",
            "babel-loader": "^8.0.5",
            "css-loader": "^5.1.3",
            "style-loader": "^2.0.0",
            "webpack": "^4.46.0",
            "webpack-cli": "^3.3.12",
            "webpack-dev-server": "^3.1.14"
        }
    }
    
    
  6. 编写webpack.config.js文件

  7. 下载相关包

  8. 运行命令

    npm run dev
    

3. Webpack核心及其使用

第一步初始化项目npm init

第二步创建webpack.config.js文件

  1. entry

    指示webpack以哪个文件作为入口起点开始进行打包

    webpack.config.js文件

    module.export = {
        // 入口起点
        entry: './src/index.js',
    }
    
  2. output

    webpack应该在哪里输出它所创建的bundle, 如何命名文件

    webpack.config.js文件

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    module.exports = {
        entry: './src/index.js',
        output: {
            // 要输出的文件名
            filename: 'my-webpack-bundle.js',
            // 文件存放路径
            path: resolve(__dirname, 'dist')
        }
    }
    
  3. loader

    webpack只能处理JavaScriptJson文件, 其他文件无法处理, loader可以让webpack能够处理其他类型的文件, 并将它们转换成有效的模块, 以供程序使用.

    webpack.config.js文件

    首先需要安装style-loader, css-loader

    npm install style-loader css-loader -D
    
    module.exports = {
      module: {
        rules: [
          {
            // 匹配后缀名为css结尾的文件
            test: /\.css$/,
            // 要使用哪些loader处理
            // loader执行顺序, 从右到左, 从上到下依次执行
            use: [
              'style-loader', // 使用<style>将css-loader内部样式注入到我们的HTML页面
              'css-loader' // 将css整合到js中
            ]
             // enforce:'post' 的含义是把该 Loader 的执行顺序放到最后
    		// enforce 的值还可以是 pre,代表把 Loader 的执行顺序放到最前面
            enforce: 'post',
          }
        ]
      }
    }
    
  4. plugins

    loader用于转换某些类型的模块, 而插件则可以用于执行范围更广的任务. 包括: 打包优化, 资源管理, 注入环境变量.

    webpack.config.js文件

    首先需要安装html-webpack-plugin

    npm install html-webpack-plugin -D
    
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/template.html'
        })
      ]
    }
    
  5. mode模式

    选项描述
    development(开发环境)会将 DefinePluginprocess.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名。
    production(生产环境)会将 DefinePluginprocess.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPluginTerserPlugin
    none不使用任何默认优化选项

    webpack.config.js文件

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
      mode: 'development' // 开发环境
    }
    

4. 打包样式资源

  1. 编写css文件

    html,
    body {
        height: 100%;
        background-color: orange;
    }
    
  2. 编写入口文件./src/index.js

    import './css/index.css'
    
    function logName(name) {
        return `love ${name}`
    }
    
    console.log(logName('chenjiang'));
    
  3. 编写webpack.config.js文件

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    module.exports = {
      entry: './src/index.js',
      watch: true,
      output: {
        // 要输出的文件名
        filename: 'my-webpack-bundle.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            // 匹配后缀名为css结尾的文件
            test: /\.css$/,
            // 要使用哪些loader处理
            // loader执行顺序, 从右到左, 从上到下依次执行
            use: [
              'style-loader', // 使用<style>将css-loader内部样式注入到我们的HTML页面
              'css-loader' // 将css整合到js中
            ]
          }
        ]
      },
      plugins: [
      
      ],
      mode: 'development'
    }
    
  4. 下载相关包

    npm install webpack webpack-cli -D
    npm install style-loader css-loader -D
    
  5. 修改packjson.json同上打包步骤

  6. 运行命令

    npm run dev
    
  7. 测试

    dist目录创建demo.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script src="./my-webpack-bundle.js"></script>
    </body>
    
    </html>
    

    在这里插入图片描述

  8. 项目结构
    在这里插入图片描述

5. 打包HTML资源

  1. 安装html-webpack-plugin插件

    npm install html-webpack-plugin -D
    

    可能出现的错误:https://blog.csdn.net/weixin_43817992/article/details/110670469

  2. 编辑webpack.config.js

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
      entry: './src/index.js',
      watch: true,
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist')
      },
      module: {
        rules: []
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板, 并且自动引入模板文件的js,css等资源文件
          template: './src/index.html',
          // 压缩HTML
          minify: {
              collapseWhitespace: true,
              removeComments: true
          }
        })
      ],
      mode: 'development'
    }
    
  3. 模板文件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <h1>My Name is ChenJiang</h1>
    </body>
    
    </html>
    
  4. 修改packjson.json同上打包步骤

  5. 运行命令

    npm run dev
    
  6. 打包成功后

    在这里插入图片描述

6. 打包图片资源

第一种: js动态生成的image和css的background-image的打包

两种打包方式:

  • 使用file-loader: 一般用来打包较大的图片
  • 使用url-loader: 一般用来打包较小的图片
  1. 编写模板文件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!-- <link rel="stylesheet" href="css/index.css"> -->
    </head>
    
    <body>
        <div class="box1"></div>
        <div class="box2"></div>
        <img src="./images/23.jpg" alt="icon">
    </body>
    
    </html>
    
  2. 编写css文件

    html,
    body {
        height: 100%;
    }
    
    div {
        width: 200px;
        height: 200px;
        margin-left: 25px;
        float: left;
    }
    
    .box1 {
        background: url('../images/22.jpg') no-repeat center;
    }
    
    .box2 {
        background: url('../images/23.jpg') no-repeat center;
    }
    
  3. 编写webpack.config.js文件

    编写好过后, 安装相关插件style-loader, css-loader, file-loader, url-loader, html-webpack-plugin

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
      entry: './src/index.js',
      watch: true,
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              'style-loader', 'css-loader'
            ]
          },
          {
            test: /\.(jpg|jpeg|png|gif)$/,
            use: [
              // 第一种使用file-loader打包图片资源
              /* {
                loader: 'file-loader',
                options: {
                  pulichPath: './dist/images',
                  outputPath: 'images'
                }
              } */
    
              // 第二种使用url-loader打包图片资源
              {
                loader: 'url-loader', // 基于file-loader, 因此用url-laoder之前, 需要安装file-loader
                options: {
                  pulichPath: './dist/images',
                  outputPath: 'images',
                  //  当打包的图片文件小于300 * 1024Byte时, 将图片编译成base64的形式,进行打包。如果大于300 * 1024Byte时,则使用file-loader进行打包
                  limit: 300 * 1024
                }
              }
    
            ]
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板
          template: './src/index.html'
        })
      ],
      mode: 'development'
    }
    
  4. 修改packjson.json同上打包步骤

  5. 使用命令进行打包

    npm run dev
    
  6. 运行结果

    小于300k的图片被转换成base64的

    遗留问题: HTML中img标签无法正常打包
    在这里插入图片描述

第二种: HTML中的img标签的图片的打包

使用html-loader

  1. webpack.config.js文件

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
      entry: './src/index.js',
      watch: true, 
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist')
      },
      module: {
        rules: [
    	//*********************************** 下面的是专门用来处理HTML文件中的img标签的 **************************************
         {
            test: /\.html$/,
            // 处理html文件的img图片(负责引入, 从而能被url-loader处理)
            use: [
              'html-loader'
            ]
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板
          template: './src/index.html'
        })
      ],
      mode: 'development'
    }
    

7. 打包其他资源

例如: 字体图标之类的

  1. 准备字体图标

    阿里矢量图标库: https://www.iconfont.cn/

    在这里插入图片描述

  2. 入口文件index.js

    import './font/iconfont.css'
    
  3. 编写webpack.config.js

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
      entry: './src/index.js',
      watch: true,
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              'style-loader', 'css-loader'
            ]
          },
            // 除了 css js html其他文件
          {
            exclude: /\.(css|js|html)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  publishPath: './dist/font',
                  outputPath: 'font'
                }
              }
            ]
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板
          template: './src/index.html'
        })
      ],
      mode: 'development'
    }
    
  4. 模板文件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!-- <link rel="stylesheet" href="css/index.css"> -->
    </head>
    
    <body>
        <span class="icon iconfont icon-2"></span>
        <span class="icon iconfont icon-3"></span>
        <span class="icon iconfont icon-4"></span>
    </body>
    
    </html>
    
  5. 修改packjson.json同上打包步骤

  6. 运行命令

    npm run dev
    
  7. 项目截图

    在这里插入图片描述

8. CSS打包到单独文件,前缀,压缩

相关包:

mini-css-extract-plugin提出css到单独文件

postcss-loader autoprefixer配合使用给css添加前缀,处理兼容的。

cssnano压缩css代码

关于使用的话可以去npm官网查看

  1. 编写webpack.config.js

    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    const { resolve } = require('path')
    module.exports = {
        entry: './src/index.js',
        watch: true,
        output: {
            // 要输出的文件名
            filename: 'built.js',
            // 文件存放路径
            path: resolve(__dirname, 'dist')
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: [
                        MiniCssExtractPlugin.loader,  // 将css提取到单独的文件
                        // 'style-loader', // 将css整合到HTML中的style中,因此不用
                        'css-loader', // 将css整合到js中
                        'postcss-loader' //添加前缀
                    ]
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './src/index.html'
            }),
            // 将css提取到单独的文件插件
            new MiniCssExtractPlugin({
                filename: "css/[name].css"
            })
        ],
        mode: 'development'
    }
    
  2. 添加postcss.config.js文件并编辑

    module.exports = {
        plugins: [
            // 添加前缀
            require('autoprefixer')({
                "overrideBrowserslist": [
                    "> 1%",
                    "last 2 versions",
                    "not ie <= 8",
                    "ios >= 8",
                    "android >= 4.0"
                ]
            }),
            // 压缩代码
            require('cssnano')({
                preset: "default"
            })
        ]
    }
    
  3. 项目结构,编写代码

    在这里插入图片描述

  4. 运行命令

    npm run dev
    
  5. 运行结果

    在这里插入图片描述

9. Eslint,es6转换es5

建议去官方文档(npm)查看相关包的使用,更新的太快了

下载包:npm install eslint-loader eslint-friendly-formatter babel-loader @babel/preset-env -D

  1. webpack.config.js配置

    const { resolve } = require('path')
    module.exports = {
        entry: './src/index.js',
        watch: true,
        output: {
            // 要输出的文件名
            filename: 'built.js',
            // 文件存放路径
            path: resolve(__dirname, 'dist')
        },
        module: {
            rules: [
                {
                    test: /\.js$/,
                    exclude: /node_modules/, // 官方包的js不检查
                    enforce: 'pre', // 两个loader中优先检查
                    use: [
                        {
                            loader: 'eslint-loader',
                            options: {
                                formatter: require('eslint-friendly-formatter') // 可以让eslint的错误信息出现在终端上
                            }
                        }
                    ]
                },
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    use: [
                        {
                            loader: 'babel-loader', // 将高级js转换成浏览器能够识别的
                            options: {
                                presets: [
                                    ['@babel/preset-env'] //                                 ['@babel/preset-env'] // 目的是告诉loader要以什么规则来转化成对应的js版本
    
                                ]
                            }
                        }
                    ]
                }
            ]
        },
        plugins: [
        ],
        mode: 'development'
    }
    
  2. 添加.eslintrc.js

    module.exports = {
        root: true,
        env: {
            node: true,
        },
        parserOptions: {
            parser: 'babel-eslint',
            ecmaVersion: 6,
            sourceType: "module"
        },
        rules: {
            "semi": ["error", "always"],
            "quotes": ["error", "double"]
        },
    };
    
  3. 入口文件

    const userName = "chenjiang";
    
    function sayName(name) {
        console.log(name);
    }
    sayName(userName);
    
  4. 编译后的文件

    eval("var userName = \"chenjiang\";\n\nfunction sayName(name) {\n  console.log(name);\n}\n\nsayName(userName);\n\n//# sourceURL=webpack://webpack_study/./src/index.js?");
    

10. 实时编译修改的文件并自动刷新页面(HMR)

前面用到了--watch, 这种只是实时打包

误区: 一开始以为webpack-dev-server能够自动打包, 后面发现只能编译, 且只能在浏览器中可以查看修改代码后的效果, 但是修改的代码并没有重新打包到dist目录下面, 编写完代码还需要打包命令

HMR(hot module replacement热模块替换):一个模块发生变化,只会重新编译这一个模块(而不是编译所有模块),极大提升构建速度

使用方法:在webpack.config.js文件里的devServer加上一个hot: true属性

注意:

  • 样式文件:可以使用HMR功能:因为style-loader内部实现了
  • js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR功能的代码。HMR功能对js的处理,只能处理非入口js文件的其他文件(入口文件import很多模块,每次HMR都会重新引入这些模块,还是会刷新页面的)。
  • html文件: 默认不能使用HMR功能,开启hot过后同时会导致问题:html文件不能热更新了(修改HTML发现不能实时更新了),HTML(不用做HMR功能,因为只有一个HTML文件)
    • 处理办法:将HTML作为入口文件
  1. webpack.config.js

    安装相关模块:npm install webpack-dev-server --save-dev

    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const { resolve } = require('path')
    module.exports = {
       entry: ['./src/index.js', './src/index.html'],
       output: {
           // 要输出的文件名
           filename: 'built.js',
           // 文件存放路径
           path: resolve(__dirname, 'dist')
       },
       module: {
           rules: [
               {
                   test: /\.css$/,
                   use: [
                       'style-loader', // 将css整合到HTML中的style中,因此不用
                       'css-loader', // 将css整合到js中
                   ]
               },
               {
                   // 必须要的
                test: /\.html$/,
                   loader: 'html-loader'
               },
           ]
       },
       plugins: [
           new HtmlWebpackPlugin({
               template: './src/index.html'
           }),
    
       ],
       mode: 'development',
       devServer: {
           contentBase: resolve(__dirname, 'dist'),
           compress: true,
           port: 8080,
           open: true,
           hot: true
       }
    }
    
  2. index.js

    import "./css/aaa.css";
    import "./css/bbb.css";
    import sayName from './js/main';
    
    const userName = "chenjiang";
    
    sayName(userName)
    
    if (module.hot) {
        // 只有下面监听的文件,修改了代码才能热更新
        module.hot.accept('./js/main', function () {
            // 会执行后面的回调函数
        })
    }
    
  3. package.json

    "scripts": {
        "start": "webpack --watch", // 打包
        "dev": "webpack serve" // 实时编译
    },
    
  4. 运行命令

    npm run dev
    

11. source-map

参考文章: https://blog.csdn.net/liwusen/article/details/79414508, https://www.jianshu.com/p/f20d4ceb8827

我们在打包中,将开发环境中源代码经过压缩,去空格,babel编译转化,最终可以得到适用于生产环境的项目代码,这样处理后的项目代码和源代码之间差异性很大,会造成无法debug的问题。

举例来说,如果压缩等处理过的生产环境中的代码出现bug,调试的时候只能定位到压缩处理后的代码的位置,无法定位到开发环境中的源代码。

  1. 没有配置source-map之前:

    错误显示的就是打包过后的位置, 这样不利于开发人员排bug

    在这里插入图片描述

  2. 配置source-map

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
      entry: './src/index.js',
      watch: true,
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist'),
        // chunkName: ''
      },
      module: {
        rules: []
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板, 并且自动引入模板文件的js,css等资源文件
          template: './src/index.html',
        })
      ],
      mode: 'development',
      devServer: {
        contentBase: resolve(__dirname, 'dist'),
        compress: true,
        port: 8080,
      },
      devtool: 'source-map' // ***********************************************
    }
    

    SourceMap又分为多种:

    编写webpack.config.js, 然后运行命令npx webpack

    1. 第一种: source-map: 会生成map格式的文件,里面包含映射关系的代码 => 外部

      在这里插入图片描述 在这里插入图片描述

    2. 第二种: inline-source-map: 不会生成map格式的文件,包含映射关系的代码会放在打包后生成的代码中 => 内联

    3. 第三种: inline-cheap-source-map: cheap有两种作用:一是将错误只定位到行,不定位到列。二是映射业务代码,不映射loader和第三方库等。
      会提升打包构建的速度。 => 内联

    4. 第四种: inline-cheap-module-source-map: module会映射loader和第三方库 => 内联

    5. 第五种: eval-source-map: 每一个文件的eval都生成对应的source-map,都在eval, 错误代码准确信息 和 源代码的错误位置 => 内联

    内联 和 外部的区别:1. 外部生成了文件,内联没有 2. 内联构建速度更快

    推荐方式: 开发环境: devtool: 'cheap-module-eval-source-map', 生产环境: devtool: 'cheap-module-source-map',

12. babel缓存

  1. 开启babel缓存,在第二次打包时,打包构建速度更快
  2. babel-loader在执行的时候,可能会产生一些运行期间重复的公共文件,造成代码体积大冗余,同时也会减慢编译效率
  3. 提高服务器访问速度, 因为第二次是从内存读取, 而不是重新加载
  1. webpack.config.js打开缓存

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    module.exports = {
      entry: './src/index.js',
      output: {
        // 要输出的文件名
        filename: 'built.js',
        // 文件存放路径
        path: resolve(__dirname, 'dist'),
    
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: [
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    ['@babel/preset-env', { targets: "defaults" }] // 目的是告诉loader要以什么规则来转化成对应的js版本
                  ],
                  cacheDirectory: true // **************************开启缓存*******************************
                }
              }
            ]
          }, {
            test: /\.css$/,
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader'
            ]
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          // 默认生成空白的HTML文档, 因此需要一个HTML模板, 并且自动引入模板文件的js,css等资源文件
          template: './src/index.html',
        }),
        new MiniCssExtractPlugin({
          filename: 'css/[name].css'
        })
      ],
      mode: 'development',
      devServer: {
        contentBase: resolve(__dirname, 'dist'),
        compress: true,
        port: 8080,
      },
    }
    
  2. 创建一个服务器

    const express = require('express')
    const app = express()
    
    app.use(express.static('dist', {
        maxAge: 1000 * 60
    }))
    
    app.listen(3000, () => {
        console.log('服务器启动中...');
    })
    
    
  3. 访问: localhost:3000

    第一次访问:

    在这里插入图片描述

    第二次访问:

    在这里插入图片描述

    第一次访问的时候, 会加载相关js和css文件

    第二次访问的话, 首先浏览器会去看看有没有相关文件的缓存, 如果有的话直接读取缓存, 不会重新加载, 这样大大提高了加载速度

    出现问题

    我修改了文件, 然后重新打包, 刷新页面, 发现页面并没有改变

    原因: 由于加载的文件名没有改变, 在缓存时间内浏览器在缓存还可以找到, 就不会重新发送请求

    解决办法: 每次打包给js和css等资源文件, 加上一个随机码, 每次访问页面, 浏览器看到请求的文件名不同, 就会重新加载, 第二次就不会加载, 直接读取缓存

    第一种: 使用hash

    添加一个hash值(所有的js和css都是一样的hash值), 每次重新打包hash值都不一样, 那么浏览器查找不到对应的缓存, 就会重新加载

    缺点: 如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件), 造成加载速度丢失

    webpack.config.js

        output: {
            // 要输出的文件名
            filename: 'built.[hash:10].js',
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name][hash:10].css'
            })
        ],
    

    第二种: chunkhash

    根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样

    所有文件都在入口文件中引入, chunk入口文件, 那么里面的所有文件也就属于此chunk, js和css的hash值还是一样的, 因此修改一个文件, 其他缓存都会失效

    webpack.config.js

        output: {
            // 要输出的文件名
            filename: 'built.[chunkhash:10].js',
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name][chunkhash:10].css'
            })
        ],
    

    第三种: contenthash

    根据文件的内容生成hash值, 不同文件hash值一定不一样

    webpack.config.js

        output: {
            // 要输出的文件名
            filename: 'built.[contenthash:10].js',
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name][contenthash:10].css'
            })
        ],
    

    修改css文件过后: 内容修改了,就会重新生成hash值, 这样就避免了, 修改一个文件, 其他缓存都会失效

    在这里插入图片描述

13. tree shaking

作用: 去除无用的代码, 减少代码体积

使用前提条件: 必须使用ES6模块化, 开启production环境 process.env.NODE_ENV = 'production'

使用方法: 在package.json文件中配置"sideEffects"属性

package.json文件

"sideEffects": false 
/*
会出现的问题: 入口文件中的css文件, 无法打包, 因为js里面没有调用css文件的代码, 因此会被认为是无用代码
*/
// 处理方法
"sideEffects": ["*.css"]

14. code split

常规情况下,所有的文件都在入口文件引入,然后打包,但是最后只生成一个bundle文件,这样这个文件体积就会很大
我们就需要把入口文件里面所引入的文件,也单独打包出来(例如:入口文件我引入了jQuery,由于体积很大,我想把它单独打包)而不是一起整合到入口文件所打包的文件中

  1. 第一种方式

    使用多入口文件, 这样就可以生成多个chunk

    entry:{
        index: './src/js/index.js',
        index2: './src/js/index2.js'
    }
    
  2. 第二种方式

    webpack.config.js文件中添加optimization属性

    作用:

    • 可以将引入的node_modules中的代码单独打包成一个bundle
    • 如果有多个入口文件, 它就会自动分析有没有公共文件, 如果有的话就会打包成一个单独的bundle(文件共用, 提高性能)
    // 一般很少用多入口文件
    optimization:{
        splitChunks:{
            chunks: 'all'
        }
    }
    
  3. 第三种方式(常用)

    单入口文件 + optimization + js代码

    在这里插入图片描述
    webpack.config.js文件

    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
    

15. 懒加载和预加载

懒加载: 有些文件里面存放的是功能函数,只有等到我需要用到这个函数的时候再加载,而不是一开始将所有的文件都一起加载进来。

懒加载使用方法:optimization + js代码 (为什么要使用代码分隔:个人理解,因为后面要加载对应的js文件,因此要单独拿出来,才能按文件加载)

预加载:webpackPerfetch 会在使用之前,提前加载js文件,等其他主要资源加载完毕,浏览器空闲下来,再加载

  • index.js入口文件

    let oBtn = document.querySelector("#btn");
    oBtn.addEventListener("click", function() {
        import( /* webpackChunkName: 'aJS', webpackPerfetch: true */ './js/a')
        .then(({ add }) => {
            console.log(add(1, 2));
        })
        .catch(err => {
            console.log('文件加载失败');
        })
    })
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值