原文链接:banggan.github.io/2019/05/09/…

Webpack核心概念解析

终于忙完了论文,可以愉快的开始学习了,重拾起重学前端、webpack以及Vue的源码解读作为入职前的复习吧。整个webpack系列将分成五个大的部分进行,以webpack4.0为文档进行解读,从简单的概念解读到最后的实现。 整个知识点涉及范围:

loader

使用loader来预处理文件,把不同的静态资源(模块的结尾不是js的模块)打包成js文件

loader打包静态资源

打包图片

  • 安装使用file-loader实现:npm install file-loader -D
  • 在webpack.config.js中添加loader的配置
module.exports = {//打包项目的入口文件entry: './src/index.js',module:{rules:[{test:/\.(jpg|png|gif)$/,//打包以jpg、png、gif结尾的所有图片文件use:{loader:'file-loader',options:{//placeholder 占位符 name:'[name]_[hash].[ext]',//保持原图片的名字+hash值和后缀,主要单引号outputPath:'image/'//打包图片的位置}}}]}
}
复制代码
  • 更多的有关于file-loader的配置见文档

打包图片成base64格式

url-loader基本能实现file-loader的打包功能,适用于小图片的打包

  • 好处:图片打包成js文件,不用加载图片的地址,页面快速显示
  • 坏处:图片过大导致js文件过大

所以,当图片的大小小于limit值时会把图片打包成base64格式,大于limit值则按照file-loader打包成图片文件

  • 安装使用url-loader实现:npm install url-loader -D
  • 在webpack.config.js中添加loader的配置
module.exports = {module:{rules:[{//打包以jpg、png、gif结尾的所有图片文件test:/\.(jpg|png|gif)$/,use:{loader:'url-loader',options:{//placeholder 占位符 name:'[name]_[hash].[ext]',//保持原图片的名字+hash值和后缀,主要单引号outputPath:'image/',//打包图片的位置limit:2048}}]}
}
复制代码
  • 更多的有关于url-loader的配置见文档

打包样式css文件

需要使用css-loader、style-loader

  • css-loader:分析几个css文件的关系,合并css文件
  • style-loader:将css-loader合并的css内容挂载在页面的head部分

实现方式:

  • 安装loader实现:npm install css-loader style-loader -D
  • 在webpack.config.js中添加loader的配置
module.exports = {module: {rules: [{//打包css文件test:/\.css$/,use:['style-loader','css-loader']}]}
}
复制代码
  • 更多的有关于css-loader的配置见文档

打包样式scss文件

需要使用sass-loader、node-sass

  • 安装loader实现:npm install sass-loader node-sass -D
  • 在webpack.config.js中添加loader的配置
module.exports = {module: {rules: [{test: /\.scss$/,use:['style-loader','css-loader','sass-loader'] }]}
};复制代码

在配置中,有三个loader,执行顺序是从下到上,从右到左。在打包scss文件时,首先执行sass-loader:对sass翻译成css文件,在挂载到css-loader,最后style-loader.

  • 更多的有关于sass-loader的配置见文档

为样式添加不同浏览器的前缀

为了兼容不同的浏览器,在写样式的时候需要加上适用不同浏览器的前缀,如-o、-webkit、-moz等

-安装loader实现:npm install postcss-loader autoprefixer -D -在根目录创建postcss.config.js

moudle.exports ={plugins:[require('autoprefixer')]
}
复制代码
  • 在webpack.config.js中添加loader的配置
module.exports = {module: {rules: [{test:/\.scss$/,use:['style-loader','css-loader','sass-loader','postcss-loader']}]}
}
复制代码
  • 更多的有关于postcss-loader的配置见文档

css-loader添加不同的配置

css模块化打包
  • 场景:在文件引入的scss不仅影响当前的文件,还影响当前文件引入的其他js文件,造成样式冲突
  • 实现:css只在当前模块类有效,在配置中添加modules:true开启css的模块化打包,在引入的时候注意区分
scss文件的嵌套引用
  • 场景:scss文件通过import引入其他scss文件,导致打包的时候引入的scss文件打包错误

  • 实现:importLoader:2

  • 在webpack.config.js中添加loader的配置

module:{rules:[{//打包scss文件test:/\.scss$/,use:['style-loader',{loader:'css-loader',options:{importLoaders:2,//index.scss中通过import引入其他的scss文件,引入的scss文件在打包的时候也将依次经过所有的loadermodules:true }},'sass-loader','postcss-loader']}]}
复制代码

打包字体图标文件

在阿里巴巴矢量图标库中,把需要的字体图标下载到本地,解压。将iconfont.eot iconfont.svg iconfont.ttf iconfont.woff 四种图片文件放入到项目中,在src中新建一个放字体图标的文件夹font。将iconfont.css文件拷贝到项目中,修改对应字体的引用路径。

  • 需要安装 file-loader:npm i file-loader -D
  • 在webpack.config.js中添加loader的配置
module.exports = {...module: {rules: [{test: /\.(eot|ttf|svg|woff)$/,use:{loader:'file-loader'}},]}]}
}
复制代码
  • 更多的有关于加载字体的配置见文档

打包数据文件

如遇到json、scv、xml文件需要打包时,使用csv-loader 和 xml-loader实现。

  • 安装:npm install csv-loader xml-loader -D
  • 在webpack.config.js中添加loader的配置
  module.exports = {module: {rules: [{test: /\.(csv|tsv)$/,use: ['csv-loader']},{test: /\.xml$/,use: ['xml-loader']}]}}
复制代码
  • 更多的有关于加载数据的配置见文档

plugins

loaders可以将各个类型的静态资源打包成webpack能处理的模块,而plugins有更强大的功能。它可以从打包优化和压缩,一直到重新定义环境中的变量。

plugin可以在webpack运行到某一个时刻,自动完成一些事情。

自动生成html文件,并引入打包生成的js文件到生成的html文件中

  • 安装使用HtmlWebpackPlugin实现:npm install html-webpack-plugin -D
  • 在webpack.config.js中添加loader的配置

在src中创建一个html的模板,在HtmlWebpackPlugin的配置中引入该模板,打包后生成和模板类似的html文件并引入打包的js文件。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');module.exports = {entry: 'index.js',output: {path: path.resolve(__dirname, './dist'),filename: 'index_bundle.js'},plugins: [new HtmlWebpackPlugin({template: 'src/index.html' })]
}
复制代码
  • 更多的有关于HtmlWebpackPlugin的配置见文档

自动清除上一次打包的dist文件

先删除上一次打包的dist文件,再执行打包

  • 安装使用CleanWebpackPlugin 实现:npm install clean-webpack-plugin -D
  • 在webpack.config.js中添加loader的配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');module.exports = {entry: 'index.js',output: {path: path.resolve(__dirname, './dist'),filename: 'index_bundle.js'},plugins: [new HtmlWebpackPlugin({template: 'src/index.html' }),new CleanWebpackPlugin(['dist']), // 在打包之前,可以删除dist文件夹下的所有内容]
}
复制代码
  • 更多的有关于CleanWebpackPlugin的配置见文档

Entry与Output的基础配置

  • 需求:打包多个入口文件,对应的在出口的配置中注意命名filename避免出口文件名字冲突----使用占位符)来确保每个文件具有唯一的名称
  • 需求:打包后的文件,作为后端的接口文件,静态资源需要上传到cdn,在output中进行配置,提前加入cdn的地址。在编译时,如果不知道publicPath的地址,可以留空,在入口起点文件运行时动态设置。__webpack_public_path__ = myRuntimePublicPath
module.exports = {mode: 'development',entry: {main: './src/index.js',sub: './src/index.js'},plugins: [new HtmlWebpackPlugin({template: 'src/index.html'}), new CleanWebpackPlugin(['dist'])],output: {publicPath: 'http://cdn.com.cn', //加入cdn地址filename: '[name].js',path: path.resolve(__dirname, 'dist')}
}
复制代码
  • 更多的有关于output的配置见文档

SourceMap的配置

SourceMap是一个映射关系,打包文件和源文件的映射关系,用于开发者的调试。

在devtool中进行设置:devtool: 'source-map'打包速度会降低,在dist里面会有map映射文件

常用设置devtool说明:

  • none:在开发者模式下,默认开启sourcemap,将其关闭
  • inline前缀:不单独生成map文件,把对应的map文件以base64的形式直接打包到js文件。
  • cheap前缀:sourcemap和打包后的js同行显示,并没有映射到列忽略源自 loader 的 source。 map,并且仅显示转译后的代码,所以打包速度相对来说较快。代码出错提示不用精确显示第几行的第几个字符出错,只显示第几行出错,会提高一些性能,
  • moudle前缀:不仅映射业务代码,还会包括loader、第三方模块的错误。
  • eval前缀:打包速度最快。

development环境推荐使用: devtool: 'cheap-module-eval-source-map'

production环境推荐使用: devtool: 'cheap-module-source-map'

  • 更多的有关于devtool文档

使用WebpackDevServer提升开发效率

场景:每次在src里编写完代码都需要手动重新运行 npm run bundle,如何自动解决?

-安装:npm install webpack-dev-server –D

  • devServer参数说明
  1. contentBase :配置开发服务运行时的文件根目录
  2. open :自动打开浏览器
  3. host:开发服务器监听的主机地址
  4. compress :开发服务器是否启动gzip等压缩
  5. port:开发服务器监听的端口
  • 在 webpack.config.js 中,加 devServer
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');module.exports = {mode: 'development',devtool: 'cheap-module-eval-source-map',devServer: {contentBase: './dist',open: true,port: 8080proxy:{//配置跨域,访问的域名会被代理到本地的3000端口'/api': 'http://localhost:3000'}}
}
复制代码
  • 在 package.json 中配置
{"name": "banggan","version": "1.0.0","description": "","main": "index.js","scripts": {"bundle": "webpack","watch": "webpack --watch","start": "webpack-dev-server",},
}
复制代码
  • 更多的有关于devServer文档

如何实现自己写一个类似webpackdevserver的工具

  • 在package.json 中配置 创建一个新的指令,npm run server运行自己写的类似webpackdevserver的工具
{"name": "banggan","version": "1.0.0","description": "","main": "index.js","scripts": {"bundle": "webpack","watch": "webpack --watch","start": "webpack-dev-server","server" : "node server.js" },
}
复制代码
  • 安装express:npm install express webpack-dev-middleware -D
  • 在根目录创建一个server.js
  • 在node中直接使用webpack:webpack(config)
const express = require('express'); //引入express
const webpack = require('webpack');//引入webpack
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./webpack.config.js');//引入配置文件const complier = webpack(config); //编译一次吗,打包一次代码
const app = express();//创建express实例app.use(webpackDevMiddleware(complier, {}));app.listen(3000, () => {//监听3000端口console.log('server is running');
});
复制代码

Hot Module Replacement热模块更新

  • 场景:在程序运行中。替换、添加、替换某个模块,不需要重新加载整个页面,实现交互时更新。

  • 在 webpack.config.js 中,添加配置

module.exports = {mode: 'development',devtool: 'cheap-module-eval-source-map',devServer: {contentBase: './dist',open: true,port: 8080,hot: true,//开启热更新功能hotOnly: true//如果html功能没有实现,也不让浏览器刷新},plugins: [new HtmlWebpackPlugin({template: 'src/index.html'}), new CleanWebpackPlugin(['dist']),new webpack.HotModuleReplacementPlugin()//使用热模块插件],
}
复制代码
  • 在main.js文件中,使用 HotModuleReplacementPlugin 启用模块的热替换功能。接口暴露在moudle.hot属性下面
//如果模块启用了HMR,就可以用 module.hot.accept(),监听模块的更新。
if (module.hot) {module.hot.accept('./library.js', function() {// 使用更新过的 library 模块执行某些操作...})
}复制代码
//拒绝给定依赖模块的更新,使用 'decline' 方法强制更新失败。
module.hot.decline(dependencies // 可以是一个字符串或字符串数组
)
复制代码

注意:引入css文件时,用框架Vue,React 时,不需要写 module.hot.accept(),因为在使用css-loader,vue-loader,babel-preset时,均配置好了HMR,不需要自己重新写 如果文件没有内置HMR,需要自己手动写监听模块更新代码

结合Bable处理ES6语法

  • 场景:代码中含有ES6/ES7的代码,为了让低版本的浏览器兼容代码,需要使用Bable进行转换
  • 安装:Bable官网
//preset-env语法转换
npm install babel-loader @babel/core @babel/preset-env -D
//兼容低版本浏览器的语法,函数的补充
npm install --save @babel/polyfill复制代码
  • 在 webpack.config.js 中,添加配置
module: {rules: [{test: /\.js$/,exclude: /node_modules/, //排除在外:在node_modules中的js,babel-loader不生效loader: "babel-loader" ,options:{"presets": [["@babel/preset-env",{targets: {edge: "17",firefox: "60",chrome: "67",safari: "11.1",},//运行在大于**版本的浏览器上,,已经支持es6的高浏览器不需要转换为es5useBuiltIns:'usage' //按需添加polyfill,把业务代码中的新语法新函数都转成低版本浏览器兼容的}]]}}]
}复制代码
  • 在src目录下的index.js中顶部位置导入import "@babel/polyfill";

注意如果不是打包业务代码,而是写的类库、或者z组件库的时候不能使用@babel/polyfill实现,因为会导致声明的变量变成全局变量,污染全局环境。使用plugin-transform-runtime实现

  • 安装插件
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2复制代码
  • 在 webpack.config.js 中,添加配置
module: {rules: [{test: /\.js$/,exclude: /node_modules/,loader: "babel-loader" ,options:{"plugins": [["@babel/plugin-transform-runtime",{"corejs": 2,"helpers": true,"regenerator": true,"useESModules": false}]]}}]
}复制代码

由于babel配置的内容较多,官网推荐在根目录下创建属于babel的配置文件.babelrc文件

由于babel需要配置的内容非常多,我们需要在项目根目录下创建一个 .babelrc 文件。 就不需要在 webpack.config.js 中写 babel 的配置了。 在 .babelrc 中:

{"plugins": [["@babel/plugin-transform-runtime", {"corejs": 2,"helpers": true,"regenerator": true,"useESModules": false}]]
}
复制代码

总结

  • 在webpack.config.js中
module.exports = {mode: 'development', //开发环境进行打包,打包的代码不会压缩devtool: 'cheap-module-eval-source-map',//不带列信息,只对业务代码进行sourcemap的生成 entry: {//配置入口文件main: './src/index.js'},devServer: {//配置webpack,开发环境的调试contentBase: './dist',//启动服务器的目录open: true,//打开新的端口号8080port: 8080,hot: true,//打开热替换功能hotOnly: true},module: {//对不同的文件进行打包规则rules: [{ test: /\.js$/, //对js文件的babel-loader打包,其配置在.babelrc文件中exclude: /node_modules/, //排除在外:在node_modules中的js,babel-loader不生效loader: 'babel-loader',}, {test: /\.(jpg|png|gif)$/,//对图片进行打包use: {loader: 'url-loader',options: {name: '[name]_[hash].[ext]',outputPath: 'images/',limit: 10240//小于10240以base64的形式进行打包}} }, {test: /\.(eot|ttf|svg)$/,//字体文件的打包use: {loader: 'file-loader'} }, {test: /\.scss$/,//scss文件的打包,先用postcss-loader,在用sass-loader进行解析,最后css-loader进行挂载use: ['style-loader', {loader: 'css-loader',options: {importLoaders: 2}},'sass-loader','postcss-loader']}, {test: /\.css$/,//css文件的打包,没有sass-loader的解析use: ['style-loader','css-loader','postcss-loader']}]},plugins: [new HtmlWebpackPlugin({template: 'src/index.html'}), new CleanWebpackPlugin(['dist']),//自动清空上一次打包new webpack.HotModuleReplacementPlugin()//热替换插件],output: {//出口文件filename: '[name].js',path: path.resolve(__dirname, 'dist')}
}
复制代码

Webpack核心概念解析相关推荐

  1. Spinnaker 核心概念解析

    参考资料 API Doc:https://www.spinnaker.io/reference/api/docs.html Swagger UI:http://15.114.100.67:8084/s ...

  2. Spring源码学习(三)-- 底层架构核心概念解析

    前面,我们大概了解了Spring中的一些概念和底层工作流程,这篇是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习.​ BeanDefinition BeanDe ...

  3. Spring源码分析(二):底层架构核心概念解析

    本节主要介绍一下Spring底层中用到的"基础设施",是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习. BeanDefinition Be ...

  4. Spring之底层架构核心概念解析

    前面,我们大概了解了Spring中的一些概念和底层工作流程,现在开始将真正讲一些Spring中的概念和工作流程. ​ 一.BeanDefinition BeanDefinition表示Bean定义,B ...

  5. Spring框架(二) 底层架构核心概念解析-四万字你值得一看

    本篇文章将对Spring底层的一些概念做一些简单的分析 , 也是为了方便后续在阅读源码的时候更加的方便 BeanDefintion BeanDefintion是一个接口 , 它表示一个Bean的定义 ...

  6. flink实战--核心概念解析和应用

    扫一扫加入大数据公众号和技术交流群,了解更多大数据技术,还有免费资料等你哦 目录 简介 1.Barrier对齐(align) 检查点两种模式的区别

  7. webpack的四个核心概念

    从 webpack v4.0.0 开始,可以不用引入一个配置文件.然而,webpack 仍然还是高度可配置的.在开始前你需要先理解四个核心概念: 入口(entry) 输出(output) loader ...

  8. Go modules基础精进,六大核心概念全解析(下)

    Go 语言做开发时,路径是如何定义的?Go Mudules又为此带来了哪些改变?本文将会全面介绍Go Modules六大核心概念,包括了设计理念与兼容性原则等,掌握这些技术点对于管理和维护Go 模块有 ...

  9. Go modules基础精进,六大核心概念全解析(上)

    Go 语言做开发时,路径是如何定义的?Go Mudules又为此带来了哪些改变?本文将会全面介绍Go Modules六大核心概念,包括了设计理念与兼容性原则等,掌握这些技术点对于管理和维护Go 模块有 ...

最新文章

  1. HTML初级知识点总结(1.0)
  2. 十三条道德准则-富兰克林
  3. Condition的await()方法
  4. 将winform窗体钉在桌面上
  5. openvswitch常用命令之ovs-ofctl、ovs-appctl
  6. [C++基础]039_C++异常处理初级出门+中级进阶
  7. 用python做数学题_「文山玩Python做测试」用python做算术题,很简单
  8. cada0图纸尺寸_制图标准规定图纸幅面和格式_A0,A1,A2,A3,A4图纸标准大小和格式_飞翔教程...
  9. quartus ii 虚拟管脚设定
  10. 小小一方士 C# Async\Await 之 上传/下载文件进度条实现原理
  11. flutter插件出现英文
  12. [学习笔记] 银华深证100指数分级证券投资基金
  13. 机器阅读理解论文必读论文(二): Teaching Machines to Read and Comprehend
  14. Unity UGUI中的rebatch和rebuild理解
  15. 境内股指期货品种、合约类型和周期规律简介
  16. 从零开始学数据分析之——《线性代数》第三章 n维向量
  17. 周易——一本不可不读,读后难忘的经典
  18. 018-JL,JNGE JLE,JNG JG,JNLE JGE,JNL带符号条件转移指令小结
  19. 企业破产重整网_企业破产重整的基本流程是怎样的?
  20. 神马笔记 版本2.0.0——新的旅程

热门文章

  1. 汇编语言的准备知识--给初次接触汇编者 (1-4) 转载
  2. js判断时间两小时之内_js判断两个时间的大小
  3. python计时器timeit返回秒数_python中的计时器timeit的使用方法
  4. 自考计算机科学与技术本科毕业论文选题,自考计算机科学与技术专业(本)毕业论文写作指导...
  5. php 照片变成卡通照片,Photoshop实例:变照片为卡通漫画
  6. 光流 | 基于HS光流算法的稠密光流提取(Matlab源代码)
  7. Matlab | Matlab从入门到放弃(14)——基于Matlab的多变量数据分析
  8. 2011计算机2级,全国计算机等级考试四合一过关训练:2级C语言程序设计(2011版)...
  9. 【数据科学】 推荐一个更高效的数据清洗方法,建议收藏
  10. 【Python】55个案例:吃透Python字符串格式化