Webpack 打包文件
虽然,我们可以直接通过命令的来打包,但是推荐创建一个 webpack.config.js
的配置文件来实现更方便和强大的功能。
webpack
命令在运行的时候,默认会读取运行命令所在的目录下的 webpack.config.js
文件,通常我们会在项目的根目录下运行命令和创建配置文件。
打包配置
- 文件目录列表
- webpack.config.js 文件核心代码
module.exports = {
// mode: 配置打包出来的文件样式
// production : 默认 压缩版
// development: 未压缩
mode:'production',
entry:'./src/a.js',
}
核心配置
webpack.config.js
文件内部的核心代码
mode 打包之后的模式
指定打包后文件的格式,有三种不同的形式
- production ( 默认情况 ) 生产模式,文件中的注释、空格等均不会保留
用于产品上传时使用,内存小
- development 开发模式,文件中的注释等内容会保留
用于开发人员使用,内存较大
- none 实际效果与开发模式相同
entry
指定打包⼊口⽂文件,有三种不同的形式
- 一对一
一个入口、一个打包文件
module.exports = {
entry: './src/a.js'
}
- 多对一
多个入口、一个打包文件
module.exports = {
entry: [
'./src/a.js',
'./src/list.js',
]
}
- 多对多
多个入口、多打包文件
module.exports = {
entry: {
'index': "./src/a.js",
'list': "./src/list.js"
}
}
output
修改打包后的文件位置,默认为 dist
即自定义的打包文件存放位置,并不会影响文件内容
// 引入内置的模块( 依赖于 node.js )
const path = require("path");
module.exports = {
mode:'production',
entry:{
'index':'./src/a.js',
'list':'./src/list.js'
},
output: {
// __dirname 当前目录
// path 必须是绝对路径
path: path.resolve(__dirname, "memory"),
// filename: "bundle.js", // 生成的一个包
filename: "[name].js" // 两个包 [name] 只是占位符
}
}
打包文件深化
模块不仅仅只是 js
的文件,webpack
可以把任意文件数据作为模块进行处理
包括:非 js 文本、css、图片等等
打包别的文件需要使用额外的配置 loader
- index.js 文件中引入 txt 文件
import girl from './data/girl.txt'
console.log(girl)
console.log("我在这里啊,就在这里啊!")
- webpack.config.js 文件中配置
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: 'raw-loader'
}
}
]
}
}
- 页面效果
Loaders
对应引入不同类型的文件打包时,需要不同的 loader
但只是实现了解析,还需要手动引入到页面上
-
下载对应的 loader
npm install --save-dev 对应的loader
-
webpack.config.js 配置
module.exports = {
...,
module: {
rules: [
{
// 正则匹配对相应的指定文件
test: /\.(文件后缀)$/,
// 使用对应的 loader
use: '对应的 loader'
}
]
}
}
file loader
把识别出的资源模块,移动到指定的输出⽬目录
并且返回这个资源在输出目录的地址(字符串)
可以用来处理图片资源
- 下载
npm install --save-dev file-loader
- 使用
file-loader
解析
module.exports = {
...,
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
use: {
loader: "file-loader",
options: {
// placeholder 占位符 [name] 源资源模块的名称
// [ext] 源资源模块的后缀
name: "[name]_[hash].[ext]",
//打包后的存放位置
outputPath: "./images",
// 打包后文件的 url
publicPath: './images'
}
}
}
]
}
}
- 引入到页面
import pic from './data/夏.jpg'
let img = new Image();
img.src = pic;
document.body.appendChild(img);
txt 文件
- 下载
npm install --save-dev raw-loader
- 使用
raw-loader
解析
const path = require("path")
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use:'raw-loader'
}
]
}
}
- 引入到页面
import girl from './data/girl.txt'
console.log(girl)
jpg/png/gif 文件
- 下载
npm install --save-dev url-loader
- 使用
url-loader
解析
const path = require("path")
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js"
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: {
loader: 'url-loader',
options: {
/**
* path:路径
* name:文件名 可以不写
* ext:后缀
* */
// name:'[path][name].[ext]',
// 设置打包后的文件位置
outputPath:'/image',
// 设置 打包后文件返回的 url
publicPath:'./dist/image',
// 限制文件的大小,小于 300k 时,直接编译成 16位形式的代码
limit:300
}
}
}
]
}
}
- 引入到页面
import pic from './data/夏.jpg'
let img = new Image();
img.src = pic;
document.body.appendChild(img);
markdown 文件
需要 html-loader markdown-loader
配合使用
- 下载
npm install --save-dev html-loader markdown-loader
- 使用
html-loader markdown-loader
进行解析
有先后顺序的区别,执行的顺序是从后往前执行的
const path = require("path")
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js"
},
module: {
rules: [
{
test: /\.md$/,
// 执行多个 loader ,顺序从后往前
use:['html-loader','markdown-loader']
}
]
}
}
- 引入到页面
import tt from './data/2-webpack.md'
document.body.innerHTML = tt;
css 文件
单独使用 css-loader 也可以实现
但是只是实现了解析 css 文件,需要手动实现 css 样式加载到页面
- 下载
npm install --save-dev css-loader
- 使用
css-loader
进行解析
const path = require("path")
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js"
},
module: {
rules: [
{
test: /\.css$/,
use:'css-loader'
}
]
}
}
- 引入到页面
import cs from './data/cs.css'
// style 标签保存样式
let sty = document.createElement("style");
sty.innerHTML = cs[0][1];
document.head.appendChild(sty);
结合使用 style-loader 可以更简单
-
下载
npm install --save-dev css-loader style-loader
-
使用
css-loader style-loader
进行解析
有先后顺序的区别,执行的顺序是从后往前执行的
const path = require("path")
module.exports = {
mode: 'production',
entry: {
"index":'./src/index.js'
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js"
},
module: {
rules: [
{
test: /\.css$/,
// 执行多个 loader ,顺序从后往前
// use:'css-loader',
/**
* style-loader
* 直接实现挂载
* */
use:['style-loader',{
/**
* 单独执行 css-loader
* 仅仅是实现了 css 打包识别
* 无法实现直接加载到页面,
* 还需要保存到 style标签
* 然后才能使用
* */
loader:'css-loader',
options:{
url:true,// 允许借入背景图 默认开启
}
}],
}
]
}
}
- 引入到页面
import cs from './data/cs.css'
Plugins
扩展 webpack
本身的一些功能
之前介绍的 webpack 我们会发现将所有的文件都打包成了 js 文件
唯独没有 html ,但是实际操作时 html 也是需要打包起来
HtmlWebpackPlugin
打包结束后自动化生成一个 html 文件,并将打包好的一系列文件加载到 html 文件上
- npm 下载引入
npm install --save-dev html-webpack-plugin
- webpack.config.js 配置
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
title: "App Test",
/**
* 打包之后的文件名称 可以获取
*
* <title>
* <%=htmlWebpackPlugin.options.title%>
* </title>
*
* */
// 文件名 app.html
filename: "app.html",
// 被打包的 html 文件地址
template: "./public/index.html"
}),
]
};
- 打包之后的效果
- 自动获取标题
<%=htmlWebpackPlugin.options.title%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 打包之后,可以直接获取标题 -->
<title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
</body>
</html>
- 打包后的 html 文件内容
CleanWebpackPlugin
在打包之前先清除之前的压缩包
- 下载
npm install --save-dev clean-webpack-plugin
- webpack.config.js 配置
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
...
plugins: [
new CleanWebpackPlugin()
]
};
mini-css-extract-plugin
代替 style-loader
的存在,提取 CSS
到一个单独的文件中
- 下载
npm install --save-dev mini-css-extract-plugin
- webpack.config.js 配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use:[
// 'style-loader',
{
loader: MiniCssExtractPlugin.loader
},
{
loader:'css-loader',
options:{
url:true,// 允许借入背景图 默认开启
}
}],
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: './app.css'
}),
]
};
sourceMap
我们实际运行在浏览器的代码是通过 webpack
打包合并甚至是压缩混淆过的代码
所生成的代码并不利于我们的调试和错误定位,可以通过 sourceMap
来解决这个问题
sourceMap
本质是一个记录了编译后代码与源代码的映射关系的文件
我们可以通过 webpack
的 devtool
选项来开启 sourceMap
module.exports = {
mode: 'production',
devtool: 'source-map',
...
}
- 打包效果
WebpackDevServer
每次的代码修改都需要重新编译打包,刷新浏览器,特别麻烦
我们可以通过安装 webpackDevServer
来改善这方面的体验
- 下载
npm install --save-dev webpack-dev-server
- 启动指令
npx webpack-dev-server
或者在package.json
中添加scripts
{
...,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server"
}
}
- 修改 webpack.config.js 配置
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 想要,默认打开的路径
openPage:'app.html',
index:'app.html',
// 自动开启浏览器
open: true,
// 开启热更新
hot:true,
// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
hotOnly:true,
}
}
- 热更新开启后
压缩文件中的内容会被清除
每次更新新的内容
Proxy
跨域处理
- 跨域配置文件
import axios from 'axios'
export default async () => {
let res = await axios({
url:'/api'
})
console.log(res);
}
- webpack.config.js 配置
module.exports = {
...,
devServer: {
...,
// 端口
port: 8081,
// 跨域
proxy:{
'/api':{
target:'http://localhost:8989',
}
}
}
}
后端服务器配置
const Koa = require('koa');
const KoaRouter = require('koa-router');
const app = new Koa();
const router = new KoaRouter();
router.get('/', async ctx => {
ctx.redirect("/api");
ctx.body = 'api';
});
router.get('/api', async ctx => {
ctx.body = '难受不?!难受就对了';
});
app.use( router.routes() );
app.listen(8989);