webpack可以看做是模块打包机,它做的事情是,分析你的项目结构,找到javascript模块以及其它的一些浏览器不能直接运行的拓展语言(less, typsscript等),并将其打包为合适的格式以供浏览器使用。
安装本地的webpack和webpack-cli
yarn add webpack webpack-cli -D
webpack可以帮我们解析js模块,并且以当前js为准查找所有相关依赖的模块,把这些文件打包成一个文件,并且帮我们解决了浏览器模块的问题,即webpack自己实现了一套模块化的机制。
默认配置文件的名字webpack.config.js
/** webpack使用的是node语法 */
// webpack内置方法不需要额外安装
let path = require('path')
module.exports = {
// 打包模式,默认有production和development
mode: 'development',
// 入口:从哪个文件开始进行依赖打包
entry: './src/index.js',
output: {
filename: 'bundle.js', // 打包后的文件名
// path.resolve: 将相对路径转换为绝对路径
// path路径必须是一个绝对路径
// __direname: 当前目录,即当前目录下的dist目录
path: path.resolve(__dirname, 'dist'),
}
}
打包后的文件,即将模块以{key(模块文件名):value(方法体)}方式进行对象处理,递归的方式执行文件依赖,将多个模块打包为一个文件
(function (modules) { // webpack启动函数
// 先定义一个模块缓存,若这个模块加载过则不需要再次加载,直接使用缓存
var installedModules = {};
// 配置实现了require方法
function __webpack_require__(moduleId) {
// 检查模块是否在缓存中
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// 创建一个模块放入缓存中
var module = installedModules[moduleId] = {
i: moduleId,
l: false, // 是否缓存完成
exports: {}
};
// 执行模块对应的执行函数
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// 模块缓存完成
module.l = true;
// 导出模块
return module.exports;
}
// 递归加载模块文件
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
({
// 所有的依赖模块对象,以{key: value}的形式
// key(当前模块的路径)
// value(模块对应的执行函数)
"./src/index.js":
(function (module, exports) {
eval("console.log('hello word!!')\n\n//# sourceURL=webpack:///./src/index.js?");
})
});
注意:若文件名不是webpack.config.js则需要执行
npx webpack --config custom.js
也可在package.json文件的scripts中配置脚本命令
“scripts": {
”build": "webpack --config custom.js"
}
// 运行打包命令
npm run build
// 运行命令传参使用--
npm run build -- env=production
yarn add webpack-dev-server -D
// 启动服务
// webpack-dev-server并不会去打包文件,只是生成一个内存中的打包,将文件写到内存中。
npx webpack-dev-server
webpack.config.js配置文件
// 开发服务器的配置,即webpack-dev-server的配置
devServer: {
port: 3000, // 服务商品号
progress: true, // 启动服务时展示打包进度条
contentBase: './build', // 以build目录作为我们的静态服务器目录
open: true, // 自动启动服务器
compress: true, // 启动gzp压缩
}
html-webpack-plugin:将html文件当作模板文件
// 安装依赖
yarn add html-webpack-plugin -D
// 配置webpack插件
// plugins存放所有的webpack插件
plugins: [
new HtmlWebpackPlugin({
// 打包文件以template指定的文件为模板文件
template: './src/index.html',
// 打包后的模板文件名
filename: 'index.html',
// 模板文件压缩优化
minify: {
// 将模板文件中的双引号删除
removeAttributeQuotes: true,
// 将文件折叠成一行
collapseWhitespace: true
},
// 将文件添加hash以解决缓存问题
hash: true
})
]
如何引入css文件呢,以前我们都是直接在html代码中将css文件引入,但现在html是个干净的模板文件,里面不能再引入css文件,应让css文件和js文件一样进行打包按需引入,所以css文件应该在js中引入
import ('./style.css')
但直接在js文件中引入,js代码是肯定不能识别css代码的,所以会报错确少对应的loader,故我们需要在webpack中对这个css模块进行配置处理。
// 将所有的模块以合适的loader进行处理
module: {
// 模块对应的规则即loader处理
rules: [
{
// 配置所有的css文件
test: /\.css$/,
// css-loader: 解析@import这种语法,将多个css文件合并为一个css
// style-loader: 将css插入到模板文件的head标签中
// loader的特点:每个loader的功能比较单一,仅专注的做一件事,所以use可以是一个数组,多个loader组合使用
// loader的执行顺序:默认是从右向左,从下向上执行
// use: ["style-loader", "css-loader" ]
// loader也可以为对象的形式
use: [
{
loader: "style-loader",
// loader的参数处理
options: {
// 将css文件插入到head文件上面,这样html模板中引入的默认样式便不会被覆盖
insertAt: 'top'
}
},
"css-loader"
]
},
{
// less文件配置
test: /\.less$/,
use: [
"style-loader",
"css-loader",
"less-loader" // 将less编译为css
]
}
// sass文件配置顺序:node-sass, sass-loader
]
}
上面的方式会将所有的样式插入到style标签中,但如果想抽离成link的形式需要使用mini-css-extract-plugin
plugins: [
// 抽离css文件,将css编译后的文件以link的形式引入而非直接放至style标签中
new MiniCssExtractPlugin({
filename: "main.css", // 抽离后的文件名
})
],
module: {
rules: [
{
test: /\.less$/,
use: [
// "style-loader",
// 抽离css文件以link的方式引入
MiniCssExtractPlugin.loader,
"css-loader",
// autoprefixer为样式添加前缀-webkit-等,以兼容各个浏览器,
// 前缀功能依赖于postcss-loader进行处理
// 同时需要创建postcss.config.js进行配置
"postcss-loader",
"less-loader" // 将less编译为css
]
}
]
}
// postcss.config.js配置
module.exports = {
plugins: [require('autoprefixer')]
}
注意:MiniCssExtractPlugin不支持css文件压缩,需要使用optimize-css-assets-webpack-plugin
// css文件压缩
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
// js文件压缩优化
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
// 优化项处理
optimization: {
minimizer: [
// js文件压缩优化
new UglifyJsPlugin({
cache: true, // 是否进行缓存
parallel: true, // 是否并行打包,可以多文件同时进行打包
sourceMap: true, //
}),
// css文件压缩
new OptimizeCssAssetsPlugin(),
]
}
module: {
// 模块对应的规则即loader处理
rules: [
{
test: /\.js$/,
use: [
{
// 将高级语法(如es6)转化为es5
loader: 'babel-loader',
options: {
// 预设,也是plugins的一个大集合
presets: [
// 进行语法转换,如将es6转化为es5
"@babel/preset-env"
],
// babel-loader所需的所有插件
plugins: [
// 用于解析装饰器@符
["@babel/plugin-proposal-decorators", { "legacy": true }],
// 用于class类语法转换
["@babel/plugin-proposal-class-properties"]
]
}
}
]
}
]
}