webpack的常用工具以及基础配置及一些问题

 

webpack是现在最常用的打包工具,支持不同类型的资源文件模块

1.Webpack的快速上手

yarn add webpack webpack-cli --dev
//运行
yarn webpack
<!-- 在打包过程中会把import、exports转换掉,所以不需要使用 type="module" -->

2.Webpack的配置文件

在webpack.config.js文件中进行配置

const path = require('path)

module.exports={
    mode:'none',
    <!-- 入口文件 -->
    entry:'./src/main.js',
    <!-- 输出文件 -->
    output:{
        filename:'bundle.js',
        <!-- 路径拼接 -->
        path:path.join(__dirname,'dist')
    }
}

webpack有三种工作模式,在不同的环境使用不同的预设配置,默认使用production模式工作

production  生成阶段,自动优化,压缩打包

development  开发阶段,打包速度,可以进行调试辅助

none  最原始的状态打包,无其他额外操作

3.Webpack资源模块的加载

webpack默认只处理JS文件,其他类型文件的处理需要通过对应类型的加载器(loader)去进行处理

loader是webpack实现前端模块化的核心特性,借助于loader就可以实现加载任意类型的资源

  style样式文件依赖模块的安装

yarn add css-loader --dev
yarn add style-loaader --dev

   对应loader的配置

module:{
    rules:[
        {
            <!-- 匹配文件 -->
            test:'/*.css$/',
            <!-- use中的loader从后向前执行 -->
            use:[style-loader,css-loader]
        <!-- style的作用:将css-loader的转换结果追加到页面-->
        }
    ]
}

4.Webpack文件资源加载器

<!-- 图片、字体资源的处理 -->
yarn add file-loader --dev

<!-- 配置 -->
rules: [
    {
        test: /.png$/,
        use: ['file-loader']
    }
]

webpack Data URLs 与 url-loader

Data URLs可以直接表示一个文件(特殊的url)

    协议      媒体类型     编码       文件内容 

    data:[<meditype>][;base64],<data> 

    data:text/html;charset=UTF-8,<h1>conent</h1>

yarn add url-loader --dev
<!-- 配置 -->
{
    test: /.png$/,
    use: {
        loader: 'url-loader',
        options: {
            limit: 10 * 1024 //10kB
        }
    }
}

 

小文件使用Data URLs,可以减少请求次数,对文件单独提取存放,提高加载速度,url-loader对超出limit的文件自动去调用file-loader进行处理,url-loader将符合limit要求的文件转换为Data URLs。


5.webpack常用资源加载器分类

  编译转换类(转为JS代码) 如:css-loader
  文件操作类(资源拷贝到目标目录,同时经路径向外导出) 如:file-loader
  代码检查类(统一代码风格,提高代码质量) 如:eslint-loader

1. webpack对ES2015(ES6)代码的处理

如下:代码的转换需要babel的支持,安装对应的依赖

 yarn add babel-laoder @babel/core @babel/preset-env --dev
 <!-- 配置 -->
 {
     test: /.js$/,
     use: {
         loader: 'babel-loader',
         options: {
             presets: ['@babel/preset-env']
         }
     }
}

2.webpack模块的加载模式

遵循ES Modules标准的import声明;遵循CommomJS标准的require函数 ;遵循AMD标准的define函数和require函数

在loader中,加载非JavaScript也会触发资源加载:

样式代码中@import指令和url函数;HTML代码中图片样式的src属性等

 在html-loader中,默认处理img的src属性

yarn add html-loader --dev
<!-- 配置 -->
{
    test: /\.html$/,
    use: {
        loader: 'html-loader',
        options: {
            attributes: {
                list: [{
                        tag: 'img',
                        attribute: 'src',
                        type: 'src',
                    },
                    {
                        tag: 'a',
                        attribute: 'href',
                        type: 'src',
                    },
                ]
            }
    }
    }
}

6. Webpack的核心工作原理

loader机制是webpack的核心

loader的这个原理:source 通过 md-loader 得到 result(js代码),即对源码进行加工处理,得到目标代码

loader 负责资源文件从输入到输出的转换,对同一资源可以使用多个loader

我们也可以自己是写一个loader,有兴趣的可以自己尝试写一个。

7.webpack 的插件机制

增强webpack的自动化能力 loader专注于实现资源模块加载 Plugin解决除资源加载外,其他自动化工作 e.g. 清除dist目录,拷贝静态文件、压缩输出代码 loader+plugin => 实现大多数前端工程化工作

1.如下一些常用插件的配置

  clean-webpack-plugin

yarn add clean-webpack-plugin --dev
<!-- 自动清除输出目录  配置 -->
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
plugins: [
    new CleanWebpackPlugin()
]

  html-webpack-plugin

yarn html-webpack-plugin --dev
<!-- 配置 -->
plugins: [
    // 用于生成 index.html
    new HtmlWebpackPlugin({
        title: 'Webpack Plugin Sample',
        meta: {
            viewport: 'width=device-width'
        },
        template: './src/index.html'
    }),
    // 用于生成 about.html
    new HtmlWebpackPlugin({
    filename: 'about.html'
    })
]

  copy-webpack-plugin

yarn add copy-webpack-plugin --dev
<!-- 配置 -->
const CopyWebpackPlugin = require('copy-webpack-plugin')
plugins: [
    new CopyWebpackPlugin([
      'public'
    ])
]

2. webpack的插件机制的工作原理

相比于loader,plugin拥有更广泛的能力范围,plugin通过钩子机制实现 

插件:一个函数或者是一个包含apply方法的对象

<!-- 通过在声明周期的钩子挂载函数实现扩展 -->
class MyPlugin {
  apply (compiler) {
console.log('MyPlugin 启动')

    compiler.hooks.emit.tap('MyPlugin', compilation => {
      // compilation => 可以理解为此次打包的上下文
      for (const name in compilation.assets) {
        // console.log(compilation.assets[name].source())
        if (name.endsWith('.js')) {
          const contents = compilation.assets[name].source()
          const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }
    })
  }
}

8.自动编译和自动刷新

在开发过程中,如果每次都手动打包编译是不好的体验,我们可以使用watch去实现自动编译

webpack的自动编译

watch工作模式:监听文件变化,自动重新打包

运行命令:yarn webpack -watch

但实现自动编译后,当我们在开启server服务,每次修改后都要手动刷新页面,也是糟糕的体验,

全局安装 BrowserSync ,启动http server 服务
监听文件的变化,达到自动更新的目的:  brower-sync dist --files "**/*"

以上方法虽然实现了自动编译和自动刷新,但操作麻烦,同时使用2个工具;效率低(磁盘读写次数频繁),那有没有一个工具可以解决?

Webpack Dev Server

提供用于开发的 HTTP Server,集成自动编译、自动刷新浏览器等功能

yarn add webpack-dev-server --dev
<!-- 运行 -->
yarn webpack-dev-server --open

为提高效率,Webpack Dev Server 并未将打包结果写入磁盘(未生成dist目录),将打包结果暂存于内存中,http-server从内存读取信息 发送到浏览器,减少磁盘的使用,大大提高了构建效率

Webpack Dev Server 静态资源访问

但是Webpack Dev Server默认只会serve打包输出的文件,只有通过webpack打包输出的文件,才能被直接被访问,但在开发阶段,我们并未对静态资源进行打包处理,通过如下配置,实现Webpack Dev Server 静态资源访问

<!-- 其他静态资源文件也需要serve,配置如下: -->
devServer: {
    <!-- contentBase额外为开发服务器指定查找资源目录 -->
    contentBase: './public'
}

Webpack Dev Server 代理API服务器

开发与上线地址不同,需要跨域请求  ,Webpack Dev Server支持配置代理

<!-- 将GitHub API 代理到开发服务器 -->
devServer: {
  contentBase: './public',
  proxy: {
    '/api': {
        
      // http://localhost:8080/api/users -> https://api.github.com/api/users
      <!-- 目标api -->
      target: 'https://api.github.com',
      // http://localhost:8080/api/users -> https://api.github.com/users
      <!-- 路径重写 -->
      pathRewrite: {
        '^/api': ''
      },
      // 不能使用 localhost:8080 作为请求 GitHub 的主机名
      changeOrigin: true
    }
  }
}
<!-- 主机名是HTTP协议的相关概念 -->

Source Map(源代码地图)

实现了自动编译和自动刷新,但在开发过程中,如果代码报错,需要调试,却不能定位源码的位置,如果一个个去找,代码量小还好,若代码量大,是不太现实的

运行代码 ——> 通过Source Map 逆向解析 ——> 源码

Source Map 解决了源代码与运行代码之间不一致所产生的问题

devtool: 'source-map'
<!-- webpack运行时会生成map文件 -->

webpack支持12种不同的方式,每种方式的效率与效果各不相同, 效果好的,生成慢,效果差,生成快

eval —— 是否使用eval执行模块代码
cheap-source-map —— 是否包含行信息
module —— 是否能够得到loader处理之前的源代码
hidden —— 生成第三方包
nosources-source-map —— 生产环境下不暴露源码

因为有12中方式,各不相同,所以要根据不同的环境,选择合适的source map

开发模式下的选择: cheap-module-eval-source-map
<!-- 原因 -->
代码每行不超过80字符(编写习惯),代码经过loader转换后差异较大,首次打包速度慢,但重写打包相对较快

生产模式下的选择: none 或 nosources-source-map
<!-- 原因 -->
调试是开发阶段的事情
Source Map 会暴露源码


9.自动刷新的问题

在开发阶段,以开发编辑器为例,当你去调试代码修改字体样式时,会发现触发自动刷新,编辑器中的内容被清除了。

那么我们如何防止刷新的问题,1.代码内容写死  2,。 额外写代码实现刷新保存,刷新后再读取。

问题的核心:自动刷新时导致页面状态丢失

实现:页面不刷新的前提下,模块也可以及时更新 

HMR介绍(模块热替换)--Hot Module Replancement

应用程序运行的过程中,实时替换摸个模块,应用状态不受影响

热替换只将修改的模块实时替换到应用中  

HMR是webpack的最强大的功能之一,极大的提高了开发者的工作效率 

HMR 集成在webpack-dev-server中 

webpack开启 HMR

<!-- 通过命令 -->
webpack-dev-server --hot
<!-- 配置 -->
const webpack = require('webpack')
devServer: {
    hot: true
    // hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
},
plugins: [
   new webpack.HotModuleReplacementPlugin()
]

但在使用中会发现一些问题

Q1:为什么样式文件的热更新开箱即用 
style-loader中已经处理了样式文件的热更新逻辑
 Q2: 凭什么样式可以自动处理 
样式模块更新后,只需要把更新好的css替换到页面,覆盖之前的样式
而js文件是无规律可循的

当使用框架开发时,每种文件都是有规律的 

通过脚手架创建的项目内部都集成了HMR方案 

webpack 的 HMR 需要手动处理模块热替换逻辑

accept注册,第一个参数代表依赖模块路径,第二个参数:更新后的处理函数

let lastEditor = editor

module.hot.accept('./editor', () => {
  const value = lastEditor.innerHTML
  document.body.removeChild(lastEditor)
  const newEditor = createEditor()
  newEditor.innerHTML = value
  document.body.appendChild(newEditor)
  lastEditor = newEditor
})

HMR 注意事项

 1.处理HMR的代码报错会导致自动刷新,采取如下配置解决:

devServer: {
  hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
}

 2.没有设置HMR的情况下,HMR API 报错,解决如下:

//先判断是否开启了热替换
if (module.hot) {
    <!-- 具体处理过程 -->
  }

3.代码中多了些与业务无关的代码

不会影响生产环境中代码的运行

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值