webpack概述
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler )
webpack做了什么
- 语法转换
- less/sass转换成css
- ES6转换成ES5
- typescript转换成js
- html/css/js代码的压缩与合并(打包)
- webpack可以在开发期间提供一个开发环境
- 自动开启浏览器
- 自动监视文件变化
- 自动刷新浏览器
- 项目一般都需要经过webpack打包之后才上线。
webpack模块说明
webpack会把所有的资源都当成模块
- css
- js
- 图片
- 字体图标
webpack给前端开发提供了模块化的开发环境
1、node中的模块化语法,(commonjs规范)
require(...) module.exports=....
2、浏览器中模块化语法
seajs 国内,淘宝出的,(CMD规范)
requirejs 国外的(AMD规格)
...慢慢被淘汰了
3、es6中的模块化语法(模块化语法规范)
import export
目前,浏览器还是node,都不支持es6的语法,利用webpack可以转换为node语法
- 对于js文件,webpack中支持AMD、CMD、commonJS、ES6模块化等语法
- 有了webpack,我们可以在前端代码中使用任意的模块化语法
- 可以在浏览器中使用nodejs的模块化语法
const $ = require('jquery')
webpack使用步骤
- 建目录
./dist 打包后的文件目录
./src 自己的项目源码
- 项目初始化
yarn init -y
安装依赖
--save 早起npm安装包时 如果不加--save,不会记录到package.json中,从npm5版本开始已经默认自动记录可以省略
--save-dev 会将包名记录到 devDependencies 中
dependencies :项目依赖,代码中依赖的包,实际上线需要使用
devDependencies:开发依赖,只在开发阶段需要使用的包,项目上线不需要使用
yarn add webpack webpack-cli -D
配置package.json中的 scripts脚本
在package.json中可以配置 scripts脚本,配置命令如下,使用命令运行比如:npm run xxx
特殊命令:start stop 可以省略 run
npm run start => npm start
npm run stop =>npm stop
yarn中所有命令都可以省略 run
"scripts": {
//命令名称 //需要打包的文件路径 //打包后的文件路径 //压缩模式
"build": "webpack ./src/index.js -o ./dist/bundle.js --mode=production"
},
使用配置文件的情况下
"scripts": {
//命令名称
"build": "webpack"
},
- 使用命令
yarn build # 就可以使用webpack进行打包了
配置文件-webpack.config.js
如果所有的参数都拼接到webpack-dev-server的后面,非常的麻烦,因此可以提供webpack.config.js来进行配置
- 在项目的根目录下面新建
webpack.config.js
文件
const path = require('path')
// 这是一个nodejs文件
module.exports = {
// 设置入口文件,从哪个文件开始打包
entry: path.join(__dirname, 'src/index.js'),
// 设置出口,配置打包到哪里去
output: {
// 设置打包输出目录
path: path.join(__dirname, 'dist'),
// 输出文件的文件名
filename: 'bundle.js'
},
//配置模式,建议先配置为不压缩
mode: 'development'
}
- 执行命令
webpack // webpack会自动读取当前目录下的配置文件
- 模式的配置
// 设置打包的模式
//'production' 压缩版本
//'development' 开发版本
mode: 'production'
压缩多个文件内容
在入口文件中添加需要压缩的文件,require(路径....)
压缩会把添加的文件一并压缩
webpack-插件
webpack 有着丰富的插件接口(rich plugin interface)。webpack 自身的多数功能都使用这个插件接口。这个插件接口使 webpack 变得极其灵活。
html-webpack-plugin插件
我们需要将index.html模板文件打包到dist文件夹中,使用插件html-webpack-plugin完成
- 安装
npm install html-webpack-plugin --save-dev
yarn add html-webpack-plugin -D
webpack.config.js
导入
var HtmlWebpackPlugin = require('html-webpack-plugin');
- 使用
module.exports = {
//配置插件
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html')
})
],
}
webpack-loaders
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。
css-loader处理css文件
- 安装
//npm安装方式
npm install --save-dev style-loader css-loader
//yarn安装方式
yarn add style-loader css-loader -D
- 配置
//在webpack.config.js下面添加
module: {
// loader的规则
rules: [
{
// 正则表达式,用于匹配所有的css文件
test: /\.css$/,
// 使用什么样的loader进行解析
//css-loader可以让webpack可以解析css文件
//style-loader 可以让css,以动态形式显示在页面
use: [ "style-loader", "css-loader"]
}
]
},
less-loader处理less文件
- 安装
npm install --save-dev less-loader less
yarn add less-loader less -D
- 配置
{
// 匹配所有的less文件
test: /\.less$/,
use: [ "style-loader", "css-loader", "less-loader"]
}
file-loader处理图片文件
file-loader会以单独文件的形式打包到dist目录中
- 安装
npm install --save-dev file-loader
- 配置
{
// 配置图片加载
test: /\.(png|jpg|gif|jpeg)$/,
use: "file-loader"
}
url-loader处理图片文件
url-loader与file-loader一样,也可以处理图片,但是url-loader可以以base64编码的方式处理图片
实际,将图片转换成base64,需要成本,会让文件增大30%大小的体积,开发过程中,只会将小图片转换成base64,大图片依旧是单独的文件
- 安装
npm install --save-dev url-loader
yarn add -D url-loader
- 配置
{
// 配置图片加载
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options:{
//限制大小 8k=8*1024 超过8k使用file-loader处理
limit:8*1024
}
}
]
}
- base64的优点
1. 精灵图的作用:减小网络请求
2. base64:减少网络请求 通过京东查看base64编码的图片
- 设置limit参数
{
// 配置图片加载
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 限定文件大小,注意:如果文件超出了大小,会自动调用file-loader,所以安装url-loader通过都要安装file-loader
limit: 8192
}
}
]
}
url-loader处理字体图标文件
处理字体图标文件与处理图标一模一样
- 配置
{
// 配置字体图标加载
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
use: [
{
loader: 'url-loader',
options: {
// 限定文件大小
limit: 819200
}
}
]
}
babel处理高版本的ES语法
介绍
Babel 是一个 JavaScript 编译器。
今天就开始使用下一代 JavaScript 语法吧!
babel可以把最新版本的语法编译成浏览器能够兼容的代码(ES5)
使用
- 安装
npm install -D babel-loader @babel/core @babel/preset-env
yarn add -D babel-loader @babel/core @babel/preset-env
- 配置
{
test: /\.js$/,
//配置排除项
exclude: /(node_modules)/,
use: {
loader: 'babel-loader'
}
}
webpack-dev-server的使用
在开发期间,会用到webpack的一个辅助包:webpack-dev-server
,(自动刷新,打包)
webpack-dev-server
的作用
自动开启http服务
自动打开浏览器
自动监视文件的变化
引入,每次修改代码,都需要重新打包
基本使用
- 安装
npm install --save-dev webpack-dev-server
yarn add -D webpack-dev-server
- webpack.config.js中的scripts命令设置
- 配置
// webpack-dev-server提供了一个简单的服务器,并且能够实时重新加载
//在webpack.config.js中与plugins并列设置
devServer: {
//端口号
port: 9999,
//自动打开浏览器
open: true,
//热更新,差异化更新,更新效率高
hot: true
}
热更新的说明
- 开启
hot: true
- 配置
var webpack = require("webpack");
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname,"src", 'index.html')
}),
new webpack.HotModuleReplacementPlugin()
],
- 热更新与dev-server模式不会在生产环境下用,生产环境还是需要
npm run build
ES6模块化
在之前的 javascript 中一直是没有模块系统的,前辈们为了解决这些问题,提出了各种规范, 最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。而 ES6 中提供了简单的模块系统,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。
基本使用
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个 变量,就必须使用export关键字输出该变量。下面是一个JS文件,里面使用export命令输出变量。
es6 中新增了两个命令 export
和 import
, export
命令用于规定模块的对外接口(导出),import
命令用于输入其他模块提供的功能(导入)
精确导出导入
//精确导出
// a.js
export const name = 'hucc'
export const age = 18
export const desc = '很帅'
使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)
//精确导入
//main.js
import {name, age, desc} from './a.js'
console.log('从模块内部导出的内容:', name, age, desc)
export(导出)详解
上面介绍了模块化最基础的用法,export 不止可以导出函数,还可以导出对象,数组,字符串等等
//a.js
export const name = 'hucc'
export const arr = [1, 2, 3]
export const obj = {
name: 'zs',
age: 18
}
export的写法,除了像上面这样,还有另外一种。
//a.js
const name = 'hucc'
const arr = [1, 2, 3]
const obj = {
name: 'zs',
age: 18
}
// 优点:上面代码在export命令后面,使用大括号指定所要输出的一组变量。它与前一种写法是等价的,但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部,一眼看清楚输出了哪些变量。
//原样
export {
name:name,
arr:arr,
obj:obj
}
//简写
export {name, arr, obj}
export default
指定默认输出, import 无需知道变量名就可以直接使用
//a.js
export default function fn () {
console.log('哈哈')
}
//main.js
//在导入时,可以随意的使用变量名来接收
import a from './a'
a()
//export default 导出一个对象
export default {aa, bb}
//在导入时,可以随意的使用变量名来接收
import a from './a'
//注意此时的变量a
a={
aa,
bb
}
注意:export default是非常用的语法,用的很多, 以一些常用的模块为例
import $ from 'jQuery' // 加载jQuery 库
import _ from 'lodash' // 加载 lodash
import moment from 'moment' // 加载 moment
import(导入) 详解
import
为加载模块的命令,基础使用方式和之前一样
//main.js
import {name, arr, user} from './a'
//如果是export default导出的内容
import a from './a'
兼容性说明
上面介绍了,es6 中模块的使用方式,但是现在es6的模块化,无论在浏览器端还是 node.js 上都没有得到很好的支持,所以需要,一些转码的工具(babel)。使我们可以用es6的方式来编码,最后输出es5的代码。
开发项目常用配置
devServer.open(热启动)
当open
启用时,开发服务器将打开浏览器。
open: true
通过CLI使用
webpack-dev-server --open
如果未提供浏览器(如上所示),则将使用默认浏览器。要指定其他浏览器,只需传递其名称:
webpack-dev-server --open 'Google Chrome'
devServer.port(端口号)
指定要监听请求的端口号:
port: 8080
通过CLI使用 :
webpack-dev-server --port 8080
devServer.proxy(反向代理)
如果你有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用。
dev-server 使用了非常强大的 http-proxy-middleware 包。更多高级用法,请查阅其文档。
在 localhost:3000
上有后端服务的话,你可以这样启用代理:
proxy: {
"/api": "http://localhost:3000"
}
请求到 /api/users
现在会被代理到请求 http://localhost:3000/api/users
。
如果你不想始终传递 /api
,则需要重写路径:
proxy: {
"/api": {
target: "http://localhost:3000",
pathRewrite: {"^/api" : ""}
}
}
默认情况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器。如果你想要接受,修改配置如下:
proxy: {
"/api": {
target: "https://other-server.example.com",
secure: false
}
}
有时你不想代理所有的请求。可以基于一个函数的返回值绕过代理。
在函数中你可以访问请求体、响应体和代理选项。必须返回 false
或路径,来跳过代理请求。
例如:对于浏览器请求,你想要提供一个 HTML 页面,但是对于 API 请求则保持代理。你可以这样做:
proxy: {
"/api": {
target: "http://localhost:3000",
bypass: function(req, res, proxyOptions) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
}
}
}
}
如果要代理到同一目标的多个特定路径,则可以使用一个或多个具有context
属性的对象的数组:
proxy: [{
context: ["/auth", "/api"],
target: "http://localhost:3000",
}]