webpack(10) webpack扩展(插件. loader)

webpack做的事情, 仅仅是分析各个模块间的依赖关系, 将chunk里的资源合并成资源列表, 然后输出打包文件;

更多的事情, 需要loader和plugin来完成;

plugin的用法, 通过npm来找用法

1. clean-webpack-plugin:

       每次打包前清除配置文件中的输出包.

       原理: 注册compiler.hooks的emit事件, 用fs模块删除配置文件的目录;

 注意: 经过我测试, 和多文件应用时候, 必须配置filename属性, 否则clean-webpack-plugin会因为文件名相同而不起作用

2. HTML Webpack Plugin

     将打包生成的js文件放到html文件中, 然后输出;可以只生成一个html文件, 也可以指定固定的/ 多个模板html

      多页面设置: 使用多次  new HtmlWebpackPlugin({chunks:[]})

 1 module.exports = (env)=>{
 2   return {
 3     mode: env.prod ? "production" : "development",
 4     devtool:  env.prod ? "eval" : "source-map",
 5     plugins:[
 6       new HtmlWebpackPlugin({
 7         title: "My App",
 8         filename:"index.html",
 9         template:"./src/assets/index.html", //指定生成模板
10         chunks: ['index'] //根据入口中定义的chunks的值生成不同的script标签, 默认是all;
11       }),
12       new HtmlWebpackPlugin({
13         title: "abc",
14         filename:"abc.html",//这个必须有
15         template:"./src/assets/abc.html",
16         chunks: ['abc']
17       }),
18       new CleanWebpackPlugin(),
19     ],
20     
21     entry:{
22       index:"./src/index.js",
23       abc:"./src/abc.js"
24     },

原理:  检查有没有template属性, 有就读取文件, 抽象语法树分析文件,没有就生成一个空的html文件.

          检查是否有chunks的属性, 有就将第一步的文件以script标签的形式输出chunkfs选项的代码 ,生成页面文件输出

3. copy-webpack-plugin

    作用: 将已存在的静态文件, 单独的,或者全部目录, copy到输出目录中. 即在用到html-webpack-plugin时, 如果html模板文件中有静态文件引入标签, 比如<img src="./img/a.jpg">,则会导致输出的文件中, 找不到img的src,必须将html对应的静态文件打包输出, 这也就是为什么html-webpack-plugin和copy-webpack-plugin一般都同时用的原因.

new CopyPlugin({
      patterns: [
        { from: "source", to: "dest" },
        { from: "other", to: "public" },
      ],
    }),

  原理, 会根据配置读取copy的目录或文件, 然后打包后输出

4. dev-server 开发时用的服务器; 

       注意, 该命令是webpack官方出的(文档不在npm上, 在webpack上).能够自动生成一个临时服务器,解决了

  •       频繁npx webpack命令的问题,
  •       开发过程中生成的页面在服务器上模拟真实的环境. 
 用法: 按装: npm install webpack-dev-server --save-dev
      启动命令: npx webpack serve

       webpack server做的操作:

  1. 传递命令行参数,
  2. 开启watch监听,
  3. 注册钩子函数, 保存资源列表, 禁止webpack输出文件,
  4. 开启express服务器, 监听端口, 根据浏览器的请求,返回资源.   

webpack-dev-server最常用的配置就是代理服务器, 来解决跨域问题:

      情景: 1. 开发时候, 用的localhost:8080端口的服务器环境,因为需要用--watch功能和在服务器上的功能, 比如, 发送ajax请求, 单纯的浏览器上时无法办到的,

              2 但请求的服务器是后端的, 或者localhost:9000端口, 不管域名还是端口不一致, 就造成了跨域问题, 

              3. proxy正是解决这个问题的:https://webpack.docschina.org/configuration/dev-server/#devserverport

module.exports = (env) => {
  return {
    mode: env.prod ? "production" : "development",
    devtool: env.prod ? "eval" : "source-map",
    ...
    devServer: {
      open: true,
      port: 8080,
      proxy: {
        //含义是: 属性名是正则表达式//api/, 如果能匹配, 则将本次请求的协议域名端口换成属性值; 
        //即原本的http://127.0.0.1:8080/api/abc被换成了http://127.0.0.1:3000/api/abc
        "/api": "http://127.0.0.1:3000",
"changeOrigin": true //是否转换请求头信息, 针对 有些服务器会对非本服务器的请求作出限制 的请求;
}, }, }

proxy的配置需要注意的几点: 

1.如果不希望传递/api,则需要重写路径:

 1 webpack.config.js
 2 
 3 module.exports = {
 4   //...
 5   devServer: {
 6     proxy: {
 7       '/api': {
 8         target: 'http://localhost:3000',
 9         pathRewrite: { '^/api': '' }, //把匹配到的这个内容, 替换成空串
10       },
11     },
12   },
13 };
    以上配置:fetch('/api/abc') 转换成请求"http://localhost:3000/abc"

2,代理时会保留主机头的来源,可以将 changeOrigin 设置为 true 以覆盖此行为

6. file-loader和url-loader的配合使用

    6.1 file-loader

        情景: 当用require方式引入静态文件, 会导致抽象语法树无法解析图片的数据, 

原因就是在引入.jpg文件后, 抽象语法树不能解析这种二进制数据, 需要loader来帮着转换. 

 

 

 作用: (1)将require("文件路径")这种导入的文件, 作为src地址导出, 

          (2) 将导入的文件导出到输出目录

 原理: function file-loader(source){ //source是文件内容(图片内容的buffer)

          // 1.生成具有相同内容的文件到输出目录

           // 2. 返回一段代码 export default "文件名"

         }

       

//index.js
import imgSrc from './assets/img/1.png';// 说明file-loader内部是export default "文件路径"

       注意点:

  1.  这个file-loader是在打包过程中用的, 而不是打包后用到的, 所以应该用npm i -D安装;
  2.  loader和plugin是不一样的, loader是不需要引入的, 可以直接使用; 这是因为loader的配置规则写法和plugin是不一样的, 

            plugins的配置是一个数组, 直接new xxplugin, 所以得提前引入, 而loader用modlue:...user: [xxloader]这种写法, 相当于 用了require了,会找node_module目录下寻找xxloader,然后导入

                

module.exports = (env) => {
  return {
    mode: env.prod ? "production" : "development",
    devtool: env.prod ? "eval" : "source-map",
    module: {
      noParse: /jquery|lodash/,

      rules: [
        {
          test: /.(png|jpe?g|gif)$/i,
          loader: 'file-loader',//只用一个loader可以直接写,而不需要写use
          options: {
            outputPath: 'images',//也可以写"/images"
            name: '[name]_[hash:5].[ext]'//hash是fileloader生成的.
          },
        },
      ],
    },

6.2 url-loader 

    url-loader works like file-loader, but can return a DataURL if the file is smaller than a byte limit.
            file-load是生成一个文件到输出目录, 并将模块文件设置成导出路径;

            url-loader是将依赖文件转换成为:导出base64格式的字符串;

           url-loader原理:

       function url-loader(source){ //source是文件内容(图片内容的buffer)

          // 1.将buffer生成一个base64编码

           // 2. 返回一段代码  export default "base64编码"

         }

       url-loader配置注意: urlloader配置完后, 不能单独再配置一个file-loader, 就可以使用

             A Number or String specifying the maximum size of a file in bytes. If the file size is equal or greater than the limit file-loader will be used (by default) and all query parameters are passed to it.

module.exports = (env) => {
  return {
    mode: env.prod ? "production" : "development",
    devtool: env.prod ? "eval" : "source-map",
    module: {
      noParse: /jquery|lodash/,

      rules: [
        {
          test: /.(png|jpe?g|gif)$/i,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 100 * 1024,//只要文件不超过100kb,则使用base64,否则用file-loader
                //注意, 配置了url-loader后就不能再去单独配置file-loader了,否则会全部使用file-loader
                //下面的配置会自动传递给file-loader
                outputPath: 'images',
                name: '[name]_[hash:5].[ext]'
              },
            },

url-loader的作用是: 当文件很小,且数量比较大时候, 如果都用file-loader, 会增加网络请求数量, 这是以文件的体积换取网络请求的数量的

 

7. output.publicpath对webpack生成的文件的路径影响;

     1. 将webpack.config.js中的output.publicPath设置为一个字符串;

    

 2. 从webpack生成的index.js的源码中可以看出

        2.1 源码中定义了一个公共路径

 

 2.2 在导出图片时候, 导出的内容是output.publicPath + require的参数,

 2.3这样打包形成的所有文件, 都会加上publicPath, 比如经过插件HtmlWebpackPlugin形成的html文件, 它的形成的标签都是加入output.publicPath的;

这样形成的文件, 打包出来会对路径造成严重影响, 

       

 

 所以, 我们一般配置为打包的网站内容:"/",原因是:

  "/xx"是绝对路径, 会自动请求网站下的路径资源(省略了协议域名端口),如网站是http:www.abc.com; 这样就会自动请求http:www.abc.com/xx

 所有成熟的loader和插件对导出路径都会受到output.publicpath的影响.

 8 .webpack内部插件

用法: 在配置文件中, 

//webpack.config.js

const webpack = require('webpack');
module.exports = {
    plugins:[
         new webpack.BannerPlugin({
            banner: 'hello world',
        }),
new
webpack.ProvidePlugin({ //引入常用的库
              $: 'jquery',
              jQuery: 'jquery',
           }),

        ...
    ]
}

1.BannerPlugin : 为每个chunk添加头信息 Add a banner to the top of each generated chunk

2. ProvidePlugin: 在全局定义常用库

原文地址:https://www.cnblogs.com/dangdanghepingping/p/14529110.html