webpack看这一篇就够了
一、什么webpack?
webpack.jpg简单来说,就是一个前端的打包工具。
在webpack看来,万事万物皆JS;图片是JS,css是JS……
- 对比gulp与webpack
相比自动化工具gulp而言,webpack的侧重点不同。
gulp侧重于前端开发的整个过程的控制管理,像是一条流水线,整个产品从无到有,都要受它的管控。
而webpack更侧重于模块打包,像一个模块打包机,把开发中的所有资源(图片、js文件、css文件等)都可以看成模块,将浏览器不识别的文件(scss/ts/vue等),通过loader(加载器)和plugins(插件)对资源进行处理,打包为一个或多个模块。
- 常用的模块化开放方案
- 前端:
- requirejs——AMD,依赖前置,准备工作全部做完开始执行,用define定义模块,用require调用模块,在html中调用js文件用data-main属性。AMD不支持返回函数,只能导出对象,是异步的。
- seajs——CMD,依赖就近,后期requireJS也支持了CMD规范,所以CMD渐渐不用了。
- ES6:moudle(export import)——ECMA,用export或者export default导出,用import导入。这种方法最简单快捷,可以利用webpack中的babel转成es5的。
- 服务端
- commonJS——用module.exports将模块导出,可以导出对象、函数、ES5类,但是不能导出ES6类,用require导入模块。是同步的。
- 模块化方式的优点
- 解决文件之间的以来关系。
- 避免命名冲突、解决全局变量级全局函数泛用的现象。
- 解决代码的服用性。
- 更好的分离,按需加载。
通常来讲,在webpack中会区分几个不同的环境进行打包:
开发环境:src
测试环境:test
压力测试
灰度测试
……
- 生产环境:dist
二、简单总结常用的功能
- 初始化项目,生成
package.json
npm init -y
- 安装 webpack和webpack-cli
cnpm install webpack webpack-cli -D
注:-D : --save-dev , 当前依赖要安装到开发环境中 devDependencies
-S : --save , 当前依赖要安装到生产环境中 Dependencies
- 创建src文件夹(开发环境的目录)
src文件夹中必须要有一个入口文件,eg:main.js
- 创建
webpack.config.js
文件
因为
webpack
在执行的时,默认会到跟目录下面的webpack.config.js
(相当于gulpfile.js)文件
-
webpack.config.js
文件的配置项process.env查看环境变量,环境变量NODE_ENV未设置时,默认为undefined
const path = require("path"); // 配置入口文件和出口文件地址 const PATH = { app:path.join(__dirname,".//src/main.js"),//路径拼接 build:path.join(__dirname,"../dist") } // 配置webpack module.exports = { // 入口的配置 entry:{ name:PATH.app }, // 出口配置 output:{ path:PATH.build, //filename:"[name].js" //name名与entry中的一致 //判断当前是开发环境还是生产环境, filename: process.env.NODE_ENV == "development" ? "js/[name].[hash:8].js" : "js/[name].js" } }
-
打包命令(初级、基本使用)
npx webpack
打包后生成的文件.jpgnpx: 默认从当前文件的
node_modules
中找到相对应的模块
-
scripts中的命令运行
- 将webpack.config.js中的配置,拆分到config中
eg: base.config.js——对应开发与生产环境
dev.config.js——对应开发环境
pro.config.js——对应生产环境
执行命令:
config.pngnpx webpack --config config/base.config.js
- 在package.json中添加配置项
"scripts": { "dev": "webpack-dev-server --progress --config config/dev.config.js", "build": "webpack --progress --config config/pro.config.js" }
经过上面的简化配置,运行时只需要输入npm run build就可以了
注:--config:指定文件的配置 --progress为显示加载进度
-
plugins:常用的插件
webpack
中凡是用插件的地方都必须要在plugins
中进行使用
-
html-webpack-plugin——打包引入js后的html文件(需要依赖webpack-cli,所以提前安装了webpack-cli)
cnpm install html-webpack-plugin -D
-
clean-webpack-plugin——打包时,清空上一次打包的内容
cnpm install clean-webpack-plugin -D
-
copy-webpack-plugin——将开发环境的静态资源(img/css)拷贝到dist目录下
cnpm install copy-webpack-plugin -D
-
extract-text-webpack-plugin——抽离css 优化
cnpm install extract-text-webpack-plugin@next -D
-
安装
vue-loader
和vue-template-compiler
处理单文件组件cnpm install -D vue-loader vue-template-compiler
-
base.config.js添加配置
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
//添加小图标
favicon:"./favicon.ico"
}),
new CopyWebpackPlugin([
{
context: path.join(__dirname, "../public"),
from: "**/*",
to: path.join(__dirname, "../dist"),
//忽略文件
ignore: ["index.html"]
}
]),
//将定义过的其它规则复制并应用到 .vue 文件里相应语言的块。
new VueLoaderPlugin()
],
- loader:模块的转换
转换浏览器不识别的文件配置项时,要在module中配置;
-
处理vue的loader
- 在rules中添加配置项
{ test: /\.vue$/, use: ['vue-loader'] }
-
处理JS的loader
- babel-loader
- @babel/core
- @babel/preset-env
cnpm install babel-loader @babel/core @babel/preset-env -D
安装之前需要package.json同级目录下创建
.babelrc
文件,进行如下配置{ "presets": [ [ //低版本的转换 ES6 => ES5 "@babel/preset-env", { //设置浏览器版本 "targets":{ //兼容到所有浏览的最后2个版本 "browsers":["last 2 version"] } } ] ] }
- base.config.js添加以下配置
{ test: /\.js$/, loader: "babel-loader" },
- 在单页面开发中如果用async await不识别时,需要安装以下依赖:
cnpm i @babel/plugin-transform-runtime --save-dev cnpm i @babel/runtime --save
在.bablerc文件中添加配置
"plugins":["@babel/plugin-transform-runtime"]
{ "presets": [ [ "@babel/preset-env", { "targets": { "browsers": ["last 2 version"] } } ] ], "plugins": ["@babel/plugin-transform-runtime"] }
-
处理css的loader
- style-loader
- css-loader
- sass-loader
- postcss-loader
- autoprefixer
在解析
sass
的时候除了需要sass-loader
之外,还需要一个特别重要的模块node-sass
注:autoprefixer 解析CSS文件,自动添加css样式的浏览器前缀到CSS内容里
cnpm install style-loader css-loader sass-loader node-sass postcss-loader autoprefixer -D
-
dev.config.js添加配置 ,做CSS的抽离
rules: [ { test: /\.(css|scss)$/, use: ["style-loader", "css-loader", "sass-loader"] } ]
-
pro.config.js添加配置——见文章第五点
-
处理图片的loader
-
url-loader
-
file-loader
-
url-loader file-loader的区别
url-loader一般用来解析体积较小的图片,可以通过
options
中的limit
来设置图片的大小
如果图片大于limit
的大小,则用file-loader
进行解析,file-loader
一般用来解析比较大的图片cnpm install url-loader file-loader -D
- base.config.js添加配置
{ test: /\.(jpg|gif|png|svg)$/, use: { loader: "url-loader", options: { limit: 2048, // name是图片原始的名称 ext是文件的后缀名 name: "img/[name].[ext]" } } },
-
-
base.config.js中对字体的配置
{ test: /\.(woff|woff2|svg|ttf|eot)$/, use: { loader: "url-loader", options: { name: "font/[name].[ext]" } } },
- webpack-merge合并webpack配置项
配置文件被分成了许多不同的部分,那么必须以某种方式来组合他们,通常就是合并数组和对象,webpack-merge很好的做到了这一点。
cnpm install webpack-merge -D
webpack-merge做了两件事:它允许连接数组并合并对象,而不是覆盖组合。
- webpack-dev-server 创建开发环境的服务
cnpm install webpack-dev-server -D
- 处理非模块化的插件
cnpm install script-loader exports-loader -D
- 在base.config.js中的rules引入
{
//引入非模块化的插件
test: require.resolve('zepto'),
//转化成模块的方式
loader: 'exports-loader?window.Zepto!script-loader'
}
三、base.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
/*
__dirname:当前文件的绝对路径
path.join:做路径的拼接
*/
//配置入口文件和出口文件地址
const PATH = {
app: path.join(__dirname, "../src/main.js"),//路径拼接
build: path.join(__dirname, "../dist")
}
//配置webpack
module.exports = {
//入口的配置
entry: {
app: PATH.app
},
//出口配置
output: {
path: PATH.build,
filename: "[name].js"//name名与entry中的一致
},
//使用插件配置项
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",//基于当前根目录下寻找
filename: "index.html",//打包完成后生成的文件名
hash:true,//为引入js的地址添加后缀,用于清楚缓存
inject:true,//true(默认)/body/head,是否讲js文件嵌入到html中。可以制定添加到body或head后面
//chunks:["入口属性名"],//指定打包的文件
//excludeChunkds:["my"],//打包除了入口属性为my的文件
title: "M站开发",//在html中title标签中设置<%= htmlWebpackPlugin.options.title%>
minify:{
removeComments:true,//清除注释
removeAttributeQuotes:true,//清除双引号
collapseWhitespace:true,//进行折叠,并且去除空格
}
}),
new CleanWebpackPlugin(),
new CopyWebpackPlugin([
{
// 指定拷贝文件的目录
context: path.join(__dirname, "../public"),
from: "**/*",
to: path.join(__dirname, "../dist"),
//忽略文件
ignore: ["index.html"]
}
])
],
//别名的配置项
resolve: {
//文件引入的优先级,从左到右,没找到vue时会去找js,scss,art……
extensions: [".vue",".js", "scss", "art", "css", "json"],
//别名的配置
alias: {
"@": path.join(__dirname, "../src")
}
},
//loader的配置 转换浏览器不识别的文件配置项
module: {
//规则
rules: [
{
//引入非模块化的插件
test: require.resolve('zepto'),
//转化成模块的方式
loader: 'exports-loader?window.Zepto!script-loader'
},
//一个对象代表一个规则
{
test: /\.js$/,
loader: "babel-loader",
exclude: path.join(__dirname, "../node_modules")
},
{
test: /\.art$/,
loader: "art-template-loader"
},
//处理图片的loader
{
test: /\.(png|jpg|gif|svg)$/,
use: {
loader: "url-loader",
options: {
limit: 2048,
// name是图片原始的名称 ext是文件的后缀名
name: "img/[name].[ext]"
}
},
exclude: path.join(__dirname, "../node_modules")
},
//处理字体的配置项(包括iconfont字体库)
{
test: /\.(woff|woff2|svg|ttf|eot)$/,
use: {
loader: "url-loader",
options: {
name: "font/[name].[ext]"
}
},
exclude: path.join(__dirname, "../node_modules")
}
]
}
}
四、开发环境dev.config.js
- dev.config.js
const baseConfig = require("./base.config");
const webpackMerge = require("webpack-merge");
const path = require("path");
//合并
const config = webpackMerge(baseConfig,{
//当前的环境
mode:"development",
module:{
rules:[
{
test:/\.(css|scss)$/,
//cssloader的执行顺序 从右到左 从下到上
use:["style-loader","css-loader","sass-loader"],
exclude:path.join(__dirname,"../node_modules")
}
]
},
//服务器的配置项
devServer:{
//自动打开浏览器
open:true,
//设置端口号
port:9000
}
})
module.exports = config;
五、生产环境pro.config.js
- 使用postcss时,要在package.json同级目录下创建postcss.config.js文件
module.exports = {
plugins: [
//自动添加浏览器前缀
require("autoprefixer")({
overrideBrowserslist: [
"defaults",
"Android 4.1",
"iOS 7.1",
"Chrome>31",
"ff>31",//火狐
"ie>=8",
"last 2 versions",
">0%"
]
})
]
}
- pro.config.js
const path = require("path");
const baseConfig = require("./base.config");
const webpackMerge = require("webpack-merge");
const ExtractTextWebpackplugin = require("extract-text-webpack-plugin");
const config = webpackMerge(baseConfig, {
mode: "production",
module: {
rules: [
{
test: /\.(css|scss)$/,
//css抽离
use: ExtractTextWebpackplugin.extract({
//解析css、sass,postcss用来加浏览器的前缀
use: ["css-loader", "postcss-loader", "sass-loader"],
fallback: "style-loader",
}),
exclude: path.join(__dirname, "../node_modules")
}
]
},
plugins: [
new ExtractTextWebpackplugin({
filename: "css/[name].[hash:8].css"//取打包后,哈希值的后8位
})
]
})
module.exports = config;
网友评论