大家可以先去看我的前两篇文章,顺便可以点个三连哦,嚯嚯嚯~
- webpack 之 零基础使用常用的Loader
- webpack 之 零基础使用常用的Plugin
Babel : Babel · The compiler for next generation JavaScript
首先我们得了解一下babel的一些基本概念
一、什么是babel
- Babel是一个工具链
- 主要用于旧浏览器后者环境中将ECMAScript 2015+ ( ES6+ )的代码转换为向后兼容的JavaScript
- 包括 : 语法转换、源代码转换等
二、为什么需要babel呢
- babel对于前端开发来说,是不可缺少的一部分
- 开发中,如果我们想使用ES6+的语法,想要使用TypeScript,开发React项目,都离不开****Babel
三、babel的底层原理
- 从一种源代码(原生语言)转换成另一种源代码(目标语言)
- 事实上我们可以吧babel看成就是一个编译器
- babel编译器的作用就是将我们的源代码,转换成浏览器可以直接识别的另外一段源代码
babel的工作流程:解析阶段、转换阶段、生成阶段
具体一点
ok啦,接下来我们就可以开始打代码了!!!
** **四、使用babel
**babel可以用来转换,但是是通过具体的babel插件来完成的,所以我们不仅要下载babel,也需要下载你所需要的对应的插件 **
**1.**下载babel-loader和babel-core
npm install babel-loader @babel/core -D
2.下载对应的插件
@babel/plugin-transform-arrow-functions : 箭头函数转换插件
@babel/plugin-transform-block-scoping : 作用域转化插件 (const、let 关键字转换为 var)
npm install @babel/plugin-transform-arrow-functions -D
npm install @babel/plugin-transform-block-scoping -D
3.在src文件夹的js文件夹夹创建es.js
随便乱写点ES6新增的,如cosnt、剪头函数等
const message = 'hello world';
const names = [123, 321];
names.forEach((item) => console.log(item));
console.log(message);
4.在index.js中导入
import './js/es';
5.在webpack.config.js中进行配置
tip : 因为现在代码越来越多啦,全弄上来怕你们找不到在哪里,所以就先截图,然后在把代码放进去了哈~
// js文件
{
test: /\.js$/,
use: [
{
// 使用loader
loader: 'babel-loader',
options: {
// 使用的插件
plugins: ['@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-block-scoping']
}
}
]
}
6.查看效果
7.优化
因为这两个插件都是很常用的,还有一些其他常用的插件,如果我们每次都一个个去下载未免太累了,可以直接给webpack提供一个preset,webpack会根据预设来加载对应的插件列表,并传递给babel
常见的预设有 : env、react、TypeScript
**@babel/preset-env : **里面自带了ES6转换相关的插件
npm install @babel/preset-env -D
所以代码就可以修改成这样啦
// js文件
{
test: /\.js$/,
use: [
{
// 使用loader
loader: 'babel-loader',
options: {
// 使用的插件
// plugins: ['@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-block-scoping']
presets: ['@babel/preset-env']
}
}
]
}
8.再次优化 ,babel的配置文件
tip : 有多种后缀名,区别就是文件里的格式不一样,这里以.js后缀名为例子
- 在根目录下新建babel.config.js
module.exports = {
presets: ['@babel/preset-env']
};
- webpack.config.js中即可改成这样
// js文件
{
test: /\.js$/,
use: ['babel-loader']
}
五、搭建环境
为什么要搭建本地环境呢? 之前我们开发的代码,为了运行需要两个步骤
- npm run buld,编译代码
- 通过 live server 或者直接通过浏览器,打开index.html
这样效率太慢了,所以我们希望当文件变化时,可以自动完成编译和展示
为了完成自动编译,webpack提供了几种可选的方式
- webpack watch mode
- webpack-dev-server(常用)
方式一 :wabpack watch
在该模式下,webpack依赖图中的所有文件,只要有一个发生了更新,那么代码会被重新编译,我们不需要手动去运行npm run build
开启watch也有两种方式
- 在导出的配置中,添加 watch : true
- 在package.json中,把以前写的那个打包的命令后加上 -- watch
这样后是不是发现下方变成了这样 ,两种方式用一个即可
方式二 :wabpack-dev-server
上面的方式可以监听到文件的变化而打包,但是事实上本身是没有自动刷新浏览器功能的(之前是因为有live-server)
wabpack-dev-server具备自动打包和实现监听功能
1.安装webpack-dev-server
npm install webpack-dev-server -D
2.在package.json中配置
3.使用npm run serve !!!!!!
4.现在能实时更新了
但是有个细节,现在的dist文件夹是空的,其实是打包了的,不过是打包到了内存里,没有输出出来 ,这是为了提高效率。最后开发完成后,再自己npm run build一下就好啦
5.可以进行些许配置 DevServer | webpack
我这里列举一些常使用的配置
** 一。static/directory : **
- 浏览器请求打包后的资源,如果没有请求到,会自动去这个文件夹进行查找(也就是说没有打包的资源,如果放到这个文件夹里,也能进行访问)
- 可以进行动态配置,因为开发阶段时如果我们也在使用CopyWebpackPlugin插件,每次运行的效率就会比较低,所以开发阶段我们可以关闭CopyWebpackPlugin直接使用这个
- 生产阶段的时候在打开CopyWebpackPlugin (这就涉及到动态配置了,可以使用)
- 总而言之 开发阶段:使用这个 生产阶段:CopyWebpackPlugin
二。HMR : 模块热替换
- HMR => Hot Module Replacement
- 指在应用程序运行过程中,替换、添加、删除模块,而无需刷新整个页面
- 好处一 : 不重新加载整个页面,可以保留某些应用程序状态不丢失
- 好处二 : 只更新需要变化的内容,节省开发的时间
原理(理解即可)
- webpack-dev-server会创建两个服务:提供静态资源的服务(express)和socket服务(net.socket)
- express server扶着直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)
- HTM Socket Server ,是一个socket的长链接
- 当服务器监听到对应的模块发生改变时,会生成两个.json文件
- 通过长链接,直接将这两个文件发送给客户端(浏览器)
- 浏览器拿到文件后,加载这两个文件,针对修改的模块进行更新
webpack-dev-serve已经支持了HMR,我们只需要开启即可
如果不开启,当我们修改代码后****,整个页面会自动刷新,使用的是live-reloading
tip : 最好同时使用target配置
配置地方在此
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 启动gzip压缩
compress: true,
// 设置端口号
port: 9000
},
其实这样配置后,hot还是不生效,页面还是会刷新~,是因为引入的方式还要改,可恶
但是我们真实开发是不需要这样的,使用vue,react框架的时候,vue-loader等会自动支持hot,不需要我们自己来写,所以,我们只需要了解一下即可
三。proxy配置
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 启动gzip压缩,传输速率会变快
compress: true,
// 自动打开浏览器
open: true,
// 设置主机地址,默认是localhost,如果希望其他地方也可以访问,可以设置为 '0.0.0.0'
// host: '0.0.0.0',
// 设置端口号
port: 9000,
// 配置代理,解决代理问题
proxy: {
// 当遇到'/api'的时候
'/api': {
// 将目前的地址代理至target
target: 'http://localhost:8888',
// 将'/api' 重写为''
pathRewrite: {
'^/api': ''
},
// 设置允许访问https的服务器
secure: false,
// 在某些情况下会很有用
changeOrigin: true
}
},
// 设置为true时,路由跳转如果返回了404错误,会自动返回index.html的内容
historyApiFallback: true
// 也可以设置成一个对象,根据from来匹配路径,决定跳转到哪个页面
// historyApiFallback: {
// rewrites: [
// { from: /^\/$/, to: '/views/landing.html' },
// { from: /^\/subpage/, to: '/views/subpage.html' },
// { from: /./, to: '/views/404.html' },
// ],
// },
},
六、resolve模块解析 : 解决路径相关
extensions : 配置后,就不用写对应的后缀名了
alias : 配置别名,就不用写很多类似 ../ ../../../ 之类的相对路径了
// 模块解析
resolve: {
// 这些后缀名不用写
extensions: ['.js', '.json', '.vue', '.css'],
// 配置别名
alias: {
'@': path.resolve(__dirname, './src'),
commonImg: path.resolve(__dirname, './src/img')
// ...
}
},
七、如何区分开发环境 :优化
优化:把开发环境和生产环境所需的各个配置分离!!!!!!
1.在根目录创建config文件夹,并创建几个文件
2.修改package.json中的配置
可以进行配置执行的文件
build : 打包的时候,加载生产环境所需配置
serve : 开发的时候,加载开发环境所需配置
"scripts": {
"build": "webpack --config ./config/webpack.prod.config.js",
"serve": "webpack serve --config ./config/webpack.dev.config.js"
},
3.webpack.comm.config.js配置
const path = require('path'); // Node内置模块
// 插件的导入方式可能不同,具体查看文档哦
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 结构出来
const { DefinePlugin } = require('webpack');
module.exports = {
// 因为当前代码环境跑在web上,进行配置一下
target: 'web',
// 入口
entry: './src/index.js',
// 出口
output: {
path: path.resolve(__dirname, '../dist'), // 因为这里需要绝对路径,__dirname获取到的是当前文件所在路径,所以拼接一下
filename: 'js/boundle.js' // 打包后的js的文件名
},
// 模块解析
resolve: {
// 这些后缀名不用写
extensions: ['.js', '.json', '.vue', '.css'],
// 配置别名
alias: {
'@': path.resolve(__dirname, '../src'),
commonImg: path.resolve(__dirname, '../src/img')
// ...
}
},
// 配置模块
module: {
// 规则
rules: [
// css|less文件
{
test: /\.(css|less)$/, // 用正则表达式来进行匹配,匹配css|less文件
use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
},
// 图片
{
test: /\.(png|jpe?g|gif|svg)$/i, // 用正则表达式来进行匹配,匹配以这些后缀名的图片
// 自动选择
type: 'asset',
parser: {
// 数据url的条件配置
dataUrlCondition: {
// 超过100kb的图片打包,小于的弄成bast64
maxSize: 10 * 1024
}
},
// 生成
generator: {
filename: 'img/[name]__[hash:8][ext]'
}
},
// 字体文件
{
test: /\.(eot|ttf|woff2?)$/i, // 用正则表达式来进行匹配,匹配以这些后缀名的字体文件
type: 'asset/resource',
// 生成
generator: {
filename: 'font/[name]__[hash:8][ext]'
}
},
// js文件
{
test: /\.js$/,
use: ['babel-loader']
}
]
},
// 配置插件,放置着一个个的插件对象
plugins: [
// 生成index.html文件,并使用模版
new HtmlWebpackPlugin({
// 指定模版路径
template: './public/index.html',
// 顺便定义一下title
title: '超级无敌巨帅小流星'
}),
// 定义变量
new DefinePlugin({
// 这里需注意 如果只有一层引号,那么内部会去找这个变量,所以如果要写字符串的话,里面再套一层,望周知
BASE_URL: '"./"'
})
// new VueLoaderPlugin()
]
};
4.webpack-merge
因为不管是生产环境,还是开发环境,都需要公共的部分,所以需要合并,合并需要一个插件
npm install webpack-merge -D
5.webpack.dev.config.js配置
const path = require('path'); // Node内置模块
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.comm.config');
// 合并
module.exports = merge(commonConfig, {
// 设置模式
mode: 'development',
// 设置source-map,建立js映射文件,方便调试代码和错误
devtool: 'source-map',
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, './public')
},
// 模块热替换
hot: true,
// 启动gzip压缩,传输速率会变快
compress: true,
// 自动打开浏览器
open: true,
// 设置主机地址,默认是localhost,如果希望其他地方也可以访问,可以设置为 '0.0.0.0'
// host: '0.0.0.0',
// 设置端口号
port: 9000,
// 配置代理,解决代理问题
proxy: {
// 当遇到'/api'的时候
'/api': {
// 将目前的地址代理至target
target: 'http://localhost:8888',
// 将'/api' 重写为''
pathRewrite: {
'^/api': ''
},
secure: false,
// 在某些情况下会很有用
changeOrigin: true
}
},
// 设置为true时,路由跳转如果返回了404错误,会自动返回index.html的内容
historyApiFallback: true
}
});
6.webpack.prod.config.js配置
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.comm.config');
// 合并
module.exports = merge(commonConfig, {
// 设置模式
mode: 'production',
plugins: [
// 自动清空dist文件夹并重新生成
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
// 匹配你要复制的文件
patterns: [
{
// 入口
from: './public',
to: './public',
globOptions: {
// 忽略的文件
ignore: [
// public文件夹下所有的index.html文件都被忽略,不复制
'**/index.html'
]
}
}
]
})
]
});
兄弟们,webpack就告一断落了,后面如果可以再继续更新,大家一起加油!!!
版权归原作者 玄鱼殇 所有, 如有侵权,请联系我们删除。