美文网首页
webpack学习教程 loader与插件的使用

webpack学习教程 loader与插件的使用

作者: Happiness9 | 来源:发表于2021-09-26 16:54 被阅读0次

    webpack以一个默认的入口文件作为打包的起点,将所有的资源依赖关系记录,形成一个依赖关系树状图,根据这个树状图引入这些相关的资源。引入的资源形成一个chunk(代码块),分别将这些chunk进行处理(例如将es6转化,将sass预处理为css等,这些操作统一称为打包),将打包好的文件输出为静态资源bundle

    五个核心概念

    1. Entry

      指示webpack以哪个文件为打包的起点,并分析构建好内部资源依赖图。

    2. Output

      指示webpack将打包后的资源bundle输出到哪里,以及如何命名。

    3. Loader

      webpack能够去处理那些非js代码(webpack本身只理解js代码),如同翻译官的角色。loader模块下载后,课配置直接使用。

    4. Plugins

      可以用于执行范围更广泛的任务,包括从打包优化和压缩,到重新定义环境中的变量等。plugins插件下载后,还需引入才可配置使用。

    5. Mode

      development:能让代码本地调试运行的环境

      production:能让代码优化上线的运行环境

    webpack能处理js/json资源,不能处理css/img等其他资源;打包的生产环境或开发环境代码,ES6模块化已经编译为浏览器能识别的模块化;打包的生产环境比开发环境多一个js压缩的过程。

    webpack.config.js

    指示webpack需要进行的工作,运行webpack指令时,会加载文件内的配置。所有构建工具都是基于nodejs平台运行的,默认采用commonjs标准模块化。

    css文件编译处理

    style-loader:创建style标签,将已转化为js的样式资源插入,然后添加到head中生效;css-loader:将css文件转化为commonjs模块加载到js中,模块内容为样式字符串;less-loader:将less文件编译成css文件,需要依赖less插件。

    {
      test: /\.css$/, //匹配文件
      use: [ //use中loader执行顺序从后往前
        'style-loader', //创建style标签,将js中的样式资源插入,然后添加到head中生效
        'css-loader', //将css文件变成commonjs模块加载到js中,模块内容为样式字符串
      ]
    },
    
    {
      test: /\.less$/,
      use: [
        'style-loader',
        'css-loader',
        'less-loader', //将less文件编译成css文件,需要依赖less插件
        ]
    },
    

    html文件编译处理

    html-webpack-plugin:不添加任何配置,默认会创建一个空的html,自动引入打包输出的所有资源(js/css);如果需要有结构的html文件,可以进行自定义配置。

    new HtmlWebpackPlugin({
      template: './src/index', //复制./src/index.html文件,并自动引入打包输出的所有资源
      
    })
    

    图片资源编译处理

    使用url-loader(依赖file-loader,默认处理不了html中的img图片,webpack5不再使用)处理图片资源,limit配置表示图片大小小于8kb的情况下,会通过base64处理转换成字符串方式。base64可以减少请求数量,减轻服务器压力,但同时图片体积会更大,文件请求速度会更慢。

    使用html-loader处理html文件的img图片,该插件负责引入img图片,从而能被url-loader进行处理。由于url-loader是使用es6模块处理文件,而html-loader使用commonJs引入图片,解析会出问题:[object Module],此时url-loader应使用esModule配置。

    {
      test: /\.(png|jpg|gif)$/,
      loader: 'url-loader',
      options: {
        limit: 8 * 1024,
        name: '[name]_[hash:10].[ext]', //name为图片文件名;hash:10取图片hash的前10位;ext取文件原来的扩展名
        esModule: false, //关闭url-loader的es6模块化,使用commonJs解析
      }
    },
    {
        test: /\.html$/,
      loader: 'html-loader'
    }
    

    webpack5中我们使用assets-moduleurl-loader在这个版本中已经被废弃。

    {
        test: /\.(png|jpe?g|gif)/,
      type: 'assets',
      parser: {
        dataUrlCondition: {
          maxSize: 8 * 1024,
        }
      },
      generator: {
        filename: 'img/[name]_[hash:10].[ext]'
      }
    }
    

    其他资源编译处理

    {
        exclude: /\.(css|jpg|png|gif|html|less|js)$/,
      loader: 'file-loader',
      options: {
        name: '[name]_[hash:10].[ext]'
      }
    }
    

    devServer

    开发服务器,用来做自动化,能够自动编译,自动打开浏览器,自动刷新浏览器等。只会在内存中编译打包,不会有任何输出,output的配置将不再有用,终止服务器后,内存中存在的编译包将会自动删除。启动devServer指令为:webpack-dev-server(需下载该插件)

    devServer: {
      contentBase: resolve(__dirname, 'build'), //需要运行的项目的文件目录(构建后的目录),webpack5不用配置该选项(该选项已被删除)
      compress: true, //启动gzip压缩,让项目体积更小,启动更快
      port: 9006, //开发服务器的端口号
      open: true, //自动打开浏览器
    }
    

    打包文件优化

    mini-css-extract-plugin插件可以将样式文件从js代码中抽离出来,单独成一个文件目录,通过link标签引入。将css单独提取出来,可以减小js文件大小

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    {
      test: /\.css$/, //匹配文件
      use: [ //use中loader执行顺序从后往前
       // 'style-loader',
        MiniCssExtractPlugin.loader, //取代style-loader,提取出css代码
        'css-loader',
      ]
    },
    plugins: [
      new MiniCssExtractPlugin({
        filename: './css/built.css', //对输出的css文件进行重命名,注意该路径为相对路径
      })
    ]
    

    css兼容性处理

    使用postcss,依赖于插件postcss-loaderpostcss-preset-env(帮助postcss找到package.jsonbrowserslist里面的配置,通过配置加载指定的css兼容性样式,可以使兼容性精确到某一个浏览器版本。默认是找生产环境browserslist,若要找development环境,需要设置node环境变量:process.env.NODE_ENV = development

    "browserslist": { //package.json
      "development": [
        "last 1 chrome version", //兼容至少最近的一个chrome浏览器版本
        "last 1 safari version"
      ],
      "production": [
        ">0.2%", //大于99.8%的浏览器
        "not dead", //不要已经废弃的浏览器版本
        "not op_mini all", //不要op_mini浏览器,webpack5已经删除
      ]
    }
    
    { //webpack.config.js
      test: /\.css$/, //匹配文件
      use: [ //use中loader执行顺序从后往前
       // 'style-loader',
        MiniCssExtractPlugin.loader, 
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss', //固定写法
            plugins: () => [
              require('postcss-preset-env')()
            ]
          }
        },
        { //webpack5用法
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: ['postcss-preset-env']
            }
          },
        }
      ]
    },
    

    css压缩

    使用插件optimize-css-assets-webpack-pluginwebpack.config.js中直接调用插件,默认的配置已经足够。

    js语法检查

    语法检查只针对js文件,使用eslint-loader插件(依赖于eslint库),应该只检查自己的源代码,排除其他插件代码。需要在package.jsoneslintConfig设置具体的检查规则。推荐使用airbnb风格指南,指示如何规范的编写js代码。运用airbnb可以通过使用插件eslint-config-airbnb(包含react风格建议)或eslint-config-airbnb-base(不包含react风格建议)。

    eslint-config-airbnb依赖于插件eslinteslint-plugin-importeslint-plugin-reacteslint-plugin-react-hookseslint-plugin-jsx-a11y

    eslint-config-airbnb-base依赖于插件eslinteslint-plugin-import

    { 
        test: /\.js$/,
      exclude: /node_modules/,
      enforce: 'pre', //优先执行
      loader: 'eslint-loader',
      options: {
        fix: true, //自动修复代码格式问题
      }
    }
     //eslint-disable-next-line 不检查下一行代码
    { //packag.json
      "eslintConfig": {
        "extends": "airbnb-base" //使用该包进行语法检查
      }
    }
    

    js兼容性处理

    使用bable-loader插件,依赖于插件@babel/core@babel/preset-env,只能转换基本语法,如promise不能转换。

    {
      test: /\.js/,
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env'], //指示babel做怎样的兼容性处理
      }
    }
    

    全部js兼容性处理还需插件@babel/polyfill,直接在js文件中引入import '@babel/polyfill'。该插件会将所有兼容性代码全部引入,导致文件体积太大。

    按需引入需要做兼容性处理的代码,需要借助corejs,需要下载插件@babel/core。使用这种方法就不能同时使用第二种方法。

    { //有报错
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env', 
            {
              useBuiltIns: 'usage', //按需下载
              corejs: {
                version: 3, //指定corejs版本
              },
              targets: { //指定兼容性做到哪个版本浏览器
                chrome: '60',
                firefox: '60',
                ie: '9',
                safari: '10',
                edge: '17',
              }
            }
          ]
        ]
      }
    },
    

    webpack性能优化

    开发环境性能优化
    1. 优化打包构建速度

      HMRhot module replacement(热模块替换/模块热替换),一个模块发生变化,只会重新打包这一个模块(而不是打包整个模块),不会重新刷新浏览器,极大提升构建速度。devServer配置中添加hot: true就可以使用该功能。样式文件由于style-loader内部实现了HMR功能,可以实现热更新。因此在开发环境中应该使用style-loader,使样式文件打包更快;html文件默认不支持该功能,由于项目中只存在一个,html文件发生变化的时候也只需要更新这一个文件,因此不需要HMR功能;js文件默认也不支持该功能,若要实现该功能(只能处理非入口js文件),则需要添加代码:

      if(module.hot) { //为true则表示HMR功能为开启状态
        module.hot.accept('./print.js', () => {
          //module.hot.accept监听print.js文件,一旦该文件发生变化,其他模块不会重新打包构建,只会再次执行当前这个回调函数
          print();
        })
      }
      
    2. 优化代码调试

      source-map:一种提供源代码到构建后代码映射的技术,如果构建后代码出错了,通过映射,可以追踪到源代码错误位置。使用方式:在webpack.config.js中添加配置devtool: 'source-map'

      cheap-module-source-mapmodule表示会将loadersource-map也加入。开发环境推荐eval-source-map更快,生产环境推荐source-map

    生产环境性能
    1. 优化打包构建速度

      one-of可以在webpack构建的时候,相应文件只用匹配一个规则,此是有一个问题,相同类型文件不能有两个规则来处理。解决方法是,将处理相同文件的多个规则移出one-of

      rules: [{}, {oneOf: []}]
      
      babel缓存:

      配置babel-loader规则选项cacheDirectorytrue,表示在第二次构建时, 会读取之前的缓存。使第二次构建速度更快。

    2. 优化代码运行的性能

      文件资源缓存:让代码上线运行缓存更好使用

      hash:每次webpack构建时,都会生成一个唯一的hash值,将jscss文件名加上hash值,可以使每次构建后都能拿到最新的代码。但由于webpack每次构建都会生成一个新的hash值,导致所有的缓存都会失效。

      chunkhash:根据chunk生成的hash值,如果打包来源于同一个chunkhash值就一样。chunk:由入口文件加上入口文件中引入的jscss文件形成一个chunk。由于css是在js中被引入的,因此同属于一个chunk,所以在其中部分模块发生变化时,也会使这一个chunk相关的所有缓存失效。

      cotenthash:根据文件的内容生成相应的hash值,不同文件的hash值一定不一样,从而实现,当前文件内容更新,只更新当前文件的hash值,获取最新文件代码,其他文件还是来自于缓存。

      tree shaking

      去除无用代码,减少代码体积。在使用ES6模块 化,webpackmodeproduction时,会自动开启该动能。如果配置sideEffects: false表示所有代码都没有副作用,都可以进行tree shaking,这样可能会导致直接引入的代码,例如css引入被去除。配置sideEffects: [*.css],改类型文件将不会执行tree shaking

      代码分割

      可以自动将node_modules中代码单独打包成一个chunk最终输出;自动分析多入口chunk中,有没有公共的文件,如果有,会打包成单独的一个chunkimport动态导入语法,能将某个文件单独打包,实现懒加载。

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

    多进程打包

    使用thread-loader模块,开启多进程打包。在thread-loader配置后的loader将会开启过进程打包。但进程启动大约需要600ms,进程通信也有一定的开销,因此只有工作消耗时间比较长(js代码比较多),才需要多进程打包。

    {
      loader: 'thread-loader',
      options: {
        worker: 2
      }
    }
    

    相关文章

      网友评论

          本文标题:webpack学习教程 loader与插件的使用

          本文链接:https://www.haomeiwen.com/subject/hcoqnltx.html