webpack 是什么?
webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。
在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
webpack五个核心概念
1、Entry
入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
2、Output
输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
3、Loader
Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解
JavaScript)
4、Plugins
插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,
一直到重新定义环境中的变量等。
5、Mode
模式(Mode)指示 webpack 使用相应模式的配置。
development :能让代码本地调试运行的环境,比如,编译打包 js 和 json 文件,并且es6 的模块化语法转换成浏览器能识别的语法;
production:能让代码优化上线运行的环境,在开发配置功能上再添加压缩代码等功能。
webpack开发环境基本配置
开发环境
- 初始化package.json
- 下载并安装 webpack —— npm install webpack webpack-cli -D
- 创建文件
4、webpack.config.js中
下载依赖
样式资源 :npm i css-loader style-loader less-loader less -D
html资源: npm install --save-dev html-webpack-plugin
图片资源:npm install --save-dev html-loader url-loader file-loader
// resolve用来拼接绝对路径的方法
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {
entry: './src/js/index.js', // 入口文件
output: {
filename: 'js/built.js', // 输出文件
path: resolve(__dirname, 'build') // 输出路径 __dirname nodejs的变量,代表当前文件的目录绝对路径
},
module: {
rules: [
// loader的配置,不同文件必须配置不同loader处理
// use数组中loader执行顺序:从右到左,从下到上 依次执行
{
/* 处理less资源,
style-loader 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',将css文件变成commonjs模块加载js中,里面内容是样式字符串
less-loader,将less文件编译成css文件
*/
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'] },
{
// 处理css资源
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
// 处理图片资源
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
// 图片大小小于 8kb,就会被 base64 处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 给图片进行重命名 // [hash:10]取图片的 hash 的前 10 位 // [ext]取文件原来扩展名
name: '[hash:10].[ext]',
// 关闭es6模块化
// 问题:因为 url-loader 默认使用 es6 模块化解析,而 html-loader 引入图片是 commonjs
// 解析时会出问题:[object Module]
// 解决:关闭 url-loader 的 es6 模块化,使用 commonjs 解析
esModule: false,
outputPath: 'imgs'
}
},
{
// 处理html中img资源
test: /\.html$/,
loader: 'html-loader'
},
{
// 处理其他资源
// 排除 css/js/html 资源
exclude: /\.(html|js|css|less|jpg|png|gif)/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media'
}
}
]
},
plugins: [
/*
plugins的配置
功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)需要有结构的HTML文件*/
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3000,
open: true
}
};
4、运行代码
npx webpack-dev-server
生产环境基本配置
提取 css 成单独文件
原因:webpack将css打包成js,造成js文件比较大,运行过程中要先加载js再运行css,会出现闪烁现象
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
......
module: {
rules: [
{
test: /\.css$/,
use: [
// 创建style标签,将样式放入
// 'style-loader',
// 这个loader取代style-loader。作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
'css-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
// 对输出的css文件进行重命名
filename: 'css/built.css'
})
],
......
};
css兼容性处理
会自动给需要兼容性处理的样式加上前缀
npm install --save-dev postcss-loader postcss-preset-env
// 定义nodejs环境变量:决定使用browserslist的哪个环境,默认情况下会走package.json中的生产环境配置,想要走开发环境的配置,需要nodejs环境变量
process.env.NODE_ENV = 'development';
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
/*
帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
*/
// 使用loader的默认配置
// 'postcss-loader',
// 修改loader的配置
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
// postcss的插件
require('postcss-preset-env')()
]
}
}
]
}
]
},
package.json文件中
"browserslist": {
// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境:默认是看生产环境
"production": [
">0.2%", // 大于99.8%的浏览器
"not dead", // 不要已经死的浏览器
"not op_mini all" // 不要op_mini
]
}
压缩css
npm install --save-dev optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin' )plugins: [ // 压缩css new OptimizeCssAssetsWebpackPlugin()],
js 语法检查
npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, // 只检查自己写的源代码,第三方的库是不用检查的 loader: 'eslint-loader',
enforce:'pre', //优先执行, 当一个文件被多个loader处理时,一定要指定loader的执行顺序,先执行eslint再执行bable options: { // 自动修复eslint的错误 fix: true } } ] },
package.json中
"eslintConfig": { "extends": "airbnb-base" }
js兼容性处理
js兼容性处理:babel-loader @babel/core
1\. 基本js兼容性处理 --> @babel/preset-env
问题:只能转换基本语法,如promise高级语法不能转换
2\. 全部js兼容性处理 --> @babel/polyfill
问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~
3\. 需要做兼容性处理的就做:按需加载 --> core-js
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { // 预设:指示babel做怎么样的兼容性处理 presets: [ [ '@babel/preset-env', { // 按需加载 useBuiltIns: 'usage', // 指定core-js版本 corejs: { version: 3 }, // 指定兼容性做到哪个版本浏览器 targets: { chrome: '60', firefox: '60', ie: '9', safari: '10', edge: '17' } } ] ] } } ] },
js压缩
生产环境默认会压缩js
mode: 'production
压缩html
const HtmlWebpackPlugin = require('html-webpack-plugin');plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', // 压缩html代码 minify: { // 移除空格 collapseWhitespace: true, // 移除注释 removeComments: true } }) ],
webpack生产环境配置代码
const { resolve } = require('path');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');const HtmlWebpackPlugin = require('html-webpack-plugin');// 定义nodejs环境变量:决定使用browserslist的哪个环境process.env.NODE_ENV = 'production';// 复用loaderconst commonCssLoader = [ MiniCssExtractPlugin.loader, 'css-loader', { // 还需要在package.json中定义browserslist loader: 'postcss-loader', options: { ident: 'postcss', plugins: () => [require('postcss-preset-env')()] } }];module.exports = { entry: './src/js/index.js', output: { filename: 'js/built.js', path: resolve(__dirname, 'build') }, module: { rules: [ { test: /\.css$/, use: [...commonCssLoader] }, { test: /\.less$/, use: [...commonCssLoader, 'less-loader'] }, /* 正常来讲,一个文件只能被一个loader处理。 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序: 先执行eslint 在执行babel */ { // 在package.json中eslintConfig --> airbnb test: /\.js$/, exclude: /node_modules/, // 优先执行 enforce: 'pre', loader: 'eslint-loader', options: { fix: true } }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', corejs: {version: 3}, targets: { chrome: '60', firefox: '50' } } ] ] } }, { test: /\.(jpg|png|gif)/, loader: 'url-loader', options: { limit: 8 * 1024, name: '[hash:10].[ext]', outputPath: 'imgs', esModule: false } }, { test: /\.html$/, loader: 'html-loader' }, { exclude: /\.(js|css|less|html|jpg|png|gif)/, loader: 'file-loader', options: { outputPath: 'media' } } ] }, plugins: [ new MiniCssExtractPlugin({ filename: 'css/built.css' }), new OptimizeCssAssetsWebpackPlugin(), new HtmlWebpackPlugin({ template: './src/index.html', minify: { collapseWhitespace: true, removeComments: true } }) ], mode: 'production'};