webpack中模块加载器Loader、插件plugins、optimization属性

目录

模块加载器(Loader)

导入css文件

加载图片

方法一

方法二

转换es6(向下兼容es5)

html代码组件导入导出

导入less文件

自定义loader(Markdown文件加载器)

markdown-loader.js文件

webpack.config.js文件配置

插件(plugins)

清除dist目录插件

通过html-webpack-plugin插件生成html(自动引入js代码)

copy-webpack-plugin

替换内容(DefinePlugin)

分离css文件

压缩css文件

自定义插件

自定义插件作用

webpack钩子链接

optimization属性

Tree-shaking(去掉无代码)

提取公共模块配置

Scope Hoisting(作用域提升)

sideEffects(副作用)

压缩css文件


模块加载器(Loader)

webpack内部默认只会处理解析JavaScript文件,需要通过模块加载器来处理其它类型文件例如css、图片等文件。

注意use下的loader会从后往前依次执行,例如下面代码先执行css-loader后执行style-loader。

const path = require('path')
module.exports = {
  entry: {
    main: ['./src/main.js', './src/index.js']
  },
  mode: 'development',
  output: {
    filename: '[name]-bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'dist/'
  },
  devServer: {
    contentBase: 'dist',
    overlay: true,
    port: 8080,
    open: true
  },
  module: {
    rules: [
      // es6转换(向下兼容es5)
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
            loader: 'babel-loader'options: {
                presets: ['@babel/preset-env'] // @babel/preset-env包括es6的全部特性转换
            }
        }
      },
      // 分离css文件
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          }
        ]
      },
     // 加载图片 超过10KB的png图片使用file-loader处理,10KB内的用url-loader处理
     {
        test: /\.(png|jpg|gif)$/i,
        use: [
          {
            loader: 'file-loader'
          }
        ]
      },
     {
        test: /\.(png|jpg|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
                limit: 10 * 1024,  // 10KBname:'[name].[ext]',
                publicPath:'images/',
                outputPath:'images/',
                esModule:false
            }
          }
        ]
      },
      // html代码组件导入导出
      {
        test: /\.html$/i,
        use: [
          {
            loader: 'html-loader',
            options: {
                attrs: ['img:src','a:href']
            }
          }
        ]
      },
    ]
  },
  plugins: []
}

导入css文件

在src文件夹下创建main.css在main.js中通过require('./main.css')引入,命令行输入npm install style-loader css-loader -D安装css-loader(能识别CSS并加载,支持模块化、压缩、文件导入等特性)和style-loader(通过动态创建style标签的方式,让解析后的css内容能够作用到页面中)。然后将webpack.dev.js图中注释内容打开即可(test是通过正则表达式匹配文件,use中为使用的loader),再次运行webpack-dev-server --config=config/webpack.dev.js便可以在http://localhost:8080/中看到添加了css的index.html文件

加载图片

方法一

拷贝文件加载原图片file-loader。

方法二

通过url-loader将图片转换为base64字符串格式

通常搭配使用小文件使用Data URLs,减少请求次数。大文件单独提取存放,提高加载速度。

命令行输入npm install url-loader file-loader -D,配置如上代码。

这时可以在css和less文件中使用图片,(这里的图片会被默认转换为base64字符串格式,好处是浏览器不用发送请求了,直接可以读取,坏处是图片如果太大,会导致转换后体积增大30%,所以这里设置了大小限制limit,表示当大于10kb时,在dist文件夹中创建images文件夹,在该文件夹下生成图片,通过链接导入,小于时才会base64转换),

注意:

  • css和less文件中使用图片的地址是src下的图片和文件的相对地址,而html中img标签使用的地址是publicPath(静态资源的引用路径)。
  • url-loader中默认采用esmodule导出图片,可能会和webpack中commonjs导入冲突使图片显示不出来,需要设置esModule:false来关闭

转换es6(向下兼容es5)

babel是一个平台,需要配置插件去完成具体特性的转换。

所以babel-loader依赖@babel/core模块且和需要完成具体特性转换插件例如@babel/preset-env(包括es6所有的特性转换)。

命令行输入npm install -D babel-loader @babel/core @babel/preset-env,配置如上代码.

此时如果在main.js写了es6的语法会被转换成es5(在最后的输出文件main-bundle.js可以查看)。

html代码组件导入导出

使用html-loader后下面的head.html文件,可以像js代码一样导入导出使用

<head><imagesrc=""mode="" /></head>

命令行输入npm install -D html-loader,配置如上代码。

注意html引入的资源中默认只会对image中的src链接进行处理,如果是a标签链接本地图片会无法展示,可以通过opttions下的attrs中添加a:href对a标签的图片链接进行处理解决。

导入less文件

less是css预处理文件,引入了变量函数等是css处理更灵活。首先命令行输入npm install less less-loader -D,然后在src文件夹下创建header.less文件,在main.js中写入require('./header.less'),然后配置webpack.config.js,在rules数组中添加{test: /\.less$/i,use: ["style-loader","css-loader","less-loader",],},注意这里还是会生成style标签插入,想要分离出来,把"style-loader"替换为{loader:MiniCssExtractPlugin.loader},这时less文件也会被分离到index.css中(见分离css文件)

自定义loader(Markdown文件加载器)

注意use下loader处理的最后结果需要是一个字符串的导出,如果最后一个处理的loader是自定义loader,则需要返回的结果如下

return'module.export = "xxx"'return'export default "xxx"'

这样webpack最后处理将外层括号去掉,通过import 导入的自定义loader处理的文件,导入的内容就为xxx。

markdown-loader.js文件

需要安装marked包解析md文件的输入内容

const marked = require('marked')
module.exports = source => {
  // 将md文件内容转换为字符串const html = marked(source) 
  // JSON.stringify转换字符串中的换行符和引号 例如将”转为\"// 方法一:只经过自定义loader处理  return`module.export = ${JSON.stringify(html)}`// return `export default ${JSON.stringify(html)}`// 方法二: 返回的值再经过html-loader处理// return html
}

webpack.config.js文件配置

const path = require('path')
module.exports = {
  entry: {
    main: ['./src/main.js', './src/index.js']
  },
  mode: 'development',
  output: {
    filename: '[name]-bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'dist/'
  },
  devServer: {
    contentBase: 'dist',
    overlay: true,
    port: 8080,
    open: true
  },
  module: {
    rules: [
      // 自定义markdown-loader
      {
        test: /\.md$/,
        use: {
            loader: './markdown-loader'// 自定义loader:markdown-loader.js文件路径
        }
        // 方法二 //use: [//  { loader: 'html-loader' },//  { loader: './markdown-loader' }//]
      }
    ]
  },
  plugins: []
}

注意方法二是将返回的html交给html-loader处理,故use下数组中的顺序不能反。

方法二转换过程

638f15d768bf7aa7451587390e671c4c.png

插件(plugins)

清除dist目录插件

每次webpack打包文件会覆盖dist文件,之前留下的文件不会去删除,所以打包时需要先手动清空dist文件夹,然后在生成打包的文件。

命令行输入npm install clean-webpack-plugin -D,在webpack.dev.js中输入const { CleanWebpackPlugin } = require('clean-webpack-plugin'),然后在plugins数组(和module属性同级的属性)中添加new CleanWebpackPlugin()即可,这时我们每次输入命令行webpack --config=config/webpack.dev.js后都会先清空dist文件夹,然后在生成打包的文件。

通过html-webpack-plugin插件生成html(自动引入js代码)

运行命令行npm install html-webpack-plugin -D安装插件,配置webpack.dev.js中写入const HtmlWebpackPlugin = require('html-webpack-plugin')用于引入自动生成html的插件,给module.export指向的对象添加属性plugins: [new HtmlWebpackPlugin({ template: './src/index.html', title: 'example', meta: {viewport:'width=device-width' }}),new HtmlWebpackPlugin({filename:'about'})]

  • template指定的模板便是移入src文件夹下的index.html的路径,在模板中可以通过<%= htmlWebpackPlugin.options.title %>访问example。

每个实例(new HtmlWebpackPlugin)都会生成一个html文件,上面会生成一个index.html和about.html文件。每个文件都会自动引入打包好的js文件.

注意如果webpack.config.js文件是在config文件夹下,但是这里的相对路径./依然指的是项目路径即config的上层路径。最后运行webpack --config=config/webpack.dev.js后会在dist文件上生成一个index.js文件,该文件中会自动引入main-bundle.js即打包后的出口文件(不需要手动引入了,可以去掉output下的publicPath: 'dist/'属性)。

  • chunks:当有多个打包的html且有多个输出js文件,默认每个打包文件会引入多个输出js文件,可以通过chunks属性只引入指定的js文件。如下图只引入的对应的js文件。

copy-webpack-plugin

用来将静态文件(一般为public目录下内容)复制到输出文件夹下。

plugin的数组中添加new CopyWebpackPlugin(['public']),这里的public为需要复制的文件夹。

替换内容(DefinePlugin)

DefinePlugin为webpack的内置插件。const webpack=require('webpack'),plugins中添加new webpack.DefinePlugin({API_BASE_URL:'"Example Domain"'}),此时 在代码中的API_BASE_URL将会替换成"Example Domain"。

注意需要用单引号包括双引号,替换时会去掉外层的一层引号(可以使用JSON.stringify('Example Domain')去转换)

分离css文件

当css文件比较大时可以提取为一个文件通过link的方式引入(当css文件比较小时不适合,不提取为单独的文件可以减少http的请求)

命令行输入npm install mini-css-extract-plugin -D安装分离插件,在webpack.dev.js中输入const MiniCssExtractPlugin = require('mini-css-extract-plugin'),将之前配置style-loader的对象替换为{loader:MiniCssExtractPlugin.loader},最后在plugins的数组中添加new MiniCssExtractPlugin({filename:'./index.css'})即可,filename代表分离出来的css名字和地址,这里注意./表示的位置是dist文件夹下。

压缩css文件

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')然后在plugins的数组中添加new OptimizeCssAssetsWebpackPlugin()即可。

注意通常不推荐配置在plugins中,因为这样会在任何情况都使用,可以通过配置在optimization中使其只有在production环境下打包使用

自定义插件

webpack的插件需要是一个函数或者一个包含apply方法的对象。通过在生命周期的钩子中挂载函数实现扩展功能。

自定义插件作用

清除打包后文件中的注释。

webpack钩子链接

Compiler Hooks | webpack

class MyPlugin {
  // compile中包含此次构建的所有信息。 
    apply(compiler) {
        // emit钩子在webpack即将输出文件之前执行
        compiler.hooks.emit.tap("MyPlugin", compilation => {
          // MyPlugin为插件的名称,compilation理解为此次打包的上下文// compilation.assets下是一个数组包含了所有经过webpack打包后的文件信息;
        for(const name in compilation.assets) {
        // 判断文件名是否以.js结尾if(name.endsWith('.js')){
          const contents = compilation.assets[name].source()
          // 取出文件内容,将注释去掉
           const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
          // 修改新的文件信息,注意source和size属性要同步修改
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }
    })
  }
}

配置:申明上面文件后在plugins的数组中添加new MyPlugin()即可

optimization属性

用于优化输出的文件,通过在module.exports对象中添加属性optimization配置。

Tree-shaking(去掉无代码)

在webpack --mode production时会被自动调用。配置optimization: {useExports:true,minimize:true}实现,这两个属性只针对ES Module生效。

useExports:打包只导出外部使用过的成员。

minimize: 移除未被外部使用的成员。

注意:由Webpack打包的代码必须使用ES Module而不是commonjs(当配置了babel转换为commonjs时上面2个属性即使配置了也不会生效故通常可以设置modules:false来关闭转换)。

提取公共模块配置

当有多入口文件生成多个打包文件时,如果入口文件中都用到jQuery,需要都引入,这时打包文件会重复打包jquery,在的module.exports对象中添加属性optimization: {splitChunks: {chunks: 'all'}},这时便会提取公共模块配置。不会重复打包重复的模块。

Scope Hoisting(作用域提升)

设置concatenateModules:true。

尽可能的将所有模块合并输出到一个函数中。

sideEffects(副作用)

tree-shaking不会将导出且被引用的内容删除,但存在被引用而未被使用的内容,sideEffects开启后会将这些内容删除删除。

在webpack --mode production时会被自动调用。模块执行时除了导出成员之外所作的事情。

设置sideEffects:true开启功能并在package.json文件中添加sideEffects:false标识代码没有副作用,才可以生效使文件中只有被导出的文件才会被执行。

注意副作用是包括直接引入css文件或未导出成员仅执行代码。开启过后下面代码将会被去除。

import'./global.css'import'./preset.js'

可以通过在package.json中添加属性"sideEffects":["./src/preset.js","*.css"] 来保留。

压缩css文件

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')后在optimization属性下添加minimizer:[new OptimizeCssAssetsWebpackPlugin()]即可。

注意这样表示我们要自定义压缩器,会覆盖webpack内置的js压缩器,所以此时js文件将不会被压缩了,我们通过const TerserWebpackPlugin = require('terser-webpack-plugin')引入,然后在数组中添加new TerserWebpackPlugin()即也可以压缩js文件了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值