一、项目说明
-
这是一个 极简的前端项目,适合新手入门,简述如下(有详细说明)
-
启动本地服务 webpack-dev-server
-
处理资源路径
-
处理 css、scss、less
-
css3 属性前缀
-
分离css、压缩分离后的css、净化分离后的css
-
babel转换(babel7.X)
-
二、项目初始化
-
新建项目根目录 文件夹
webpack_demo_basic -
进入终端执行
npm init -y生成 package.json 文件,如下
-
初始化项目文件,目录如下
src/css/index.css 文件:css样式文件
src/less/less 文件:less样式文件
src/scss/index.scss 文件:scss样式文件
src/index.html 文件:项目html
src/index.js 文件:项目入口js
.babelrc 文件:项目babel配置文件
.gitignore 文件:git忽略配置文件(使用 Git 版本控制时,需要配置)
package.json 文件:定义了项目所需的模块,以及项目的配置信息
webpack.config.js 文件:webpack配置文件
-
安装 webpack依赖
npm i webpack@4.28.3 webpack-cli@3.2.0 -D -
webpack 基础配置
// webpack.config.js 文件 const path = require('path'); module.exports = { mode: 'development', // 开发模式 entry: './src/index.js', // 打包后输出的文件名 为 main.js /** * 或 * * entry: { * index: './src/index.js' * } */ output: { path: path.resolve(__dirname, 'dist'), // 打包后项目 输出到项目根目录下 dist 文件夹 filename: '[name].js' // 输出的 入口JS文件名称 }, // loader 相关配置 module: { rules: [] }, // 插件 相关配置 plugins: [] };
三、配置/生成 页面 html
-
插件:html-webpack-plugin
根据模板 生成页面html
自动引入 JS 等外部资源文件
设置 title 、mate 等标签内容
优化html(压缩、缓存、转换等)
-
安装
npm i html-webpack-plugin@3.2.0 -D -
配置
// webpack.config.js 文件 const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 文件名; 默认是index.html template: './src/index.html', // 指定模板html文件 title: '11111', // html文件 title标签的内容 inject: true, // 自动引入JS脚本的位置,默认值为 true(通常默认值即可满足条件) /* * 此选项有如下四种值: * * true/'body': JS脚本在 body标签底部 引入 * 'head': JS脚本在 bead标签底部 引入 * false: 不插入任何JS(几乎不会用到) */ // 如下 通常在生产模式下 才配置 hash: true, // 默认值为false, 值为true时,html 引入的脚本、scss都加hash值(清除缓存) // 建议 生产环境下 设置为 true cache: true, // 默认值为true, 设置缓存 // 建议 生产环境下 设置为 true minify: { // 建议 生产环境下 再配置此选项 minifycss: true, // 压缩css minifyJS: true, // 压缩JS minifyURLs: true, // 压缩URL removeComments: true, // 去掉注释 removeAttributeQuotes: true, // 去掉标签上 属性的双引号 collapseWhitespace: true, // 去掉空行 removeRedundantAttributes: true, // 去掉多余的属性 removeEmptyAttributes: true // 去掉空属性 } }) ] }; -
配置说明
四、配置 本地服务
-
服务器:webpack-dev-server
一个小型的 Node.js Express服务器,程序开发时 本地运行项目
-
安装
npm i webpack-dev-server@3.1.14 -D -
配置
// webpack.config.js 文件 const path = require('path'); module.exports = { devServer:{ index: 'index.html', // 服务器启动的页面(同 html-webpack-plugin 中 filename 选项); 默认值为 index.html port: 3000, // 指定端口号; 默认 8080 host: 'localhost', // 指定host; 默认 localhost /* * 或 * host: '0.0.0.0', // 可 通过IP 访问,也可以通过 localhost 访问 * useLocalIp: true, // browser open with your local IP */ open: true, // 启动本地服务后,自动打开页面 compress: true, // 是否启用 gzip 压缩 overlay: true, // 编译器错误或警告时, 在浏览器中显示全屏覆盖; 默认false progress: true, // 是否将运行进度输出到控制台; 默认 false contentBase: path.resolve(__dirname, 'dist'), // 告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要 // 精简 终端输出(本地运行时) stats: { modules: false, children: false, chunks: false, chunkModules: false } } }; -
配置说明
-
支持热更新:检测到项目中修改的代码,立即在浏览器中自动更新
新手需知道:热更新仅限于项目代码;webpack 相关的配置不会参与热更新
-
精简终端输出
-
关于 精简终端输出 详细讲解见之后的文章
-
小伙伴们可以对比下,本地运行项目时,有无 stats 选项,终端输出的变化
-
-
热替换
-
场景:建议开发环境下使用
-
好处:局部加载 页面有改动的地方;加快开发编译速度
-
关于 热替换 详细讲解见之后的文章
-
五、配置 npm script
-
在
package.json中配置相关指令,实现 本地运行、打包项目终端执行 npm run xxx,就会执行 package.json 里script对应的 xxx 指令
-
本地启动项目
-
指令配置
// packgae.json 文件 { "scripts": { "dev": "webpack-dev-server" } } -
说明
--progress、--open
{ "scripts": { "dev": "webpack-dev-server --progress --open" } } // --progress 代表: 本地启动项目终端显示进度 // --open 代表: 运行后浏览器自动打开页面 // 这两个和 webpack-dev-server 服务器的配置选项 progress、open 达到的效果一致,无需重复配置--config
{ "scripts": { "dev": "webpack-dev-server --config webpack/config.js" } } // "dev": "webpack-dev-server"` 默认去找 根目录下名为 `webpack.config.js` 的webpack配置文件,进行打包、运行 // 如果有场景要自定义 webpack 配置文件名称/路径,可以使用 --config 指定 webpack 配置文件,如上 -
项目根目录下,终端执行
npm run dev即可本地运行项目浏览地址
http://localhost:3000/
-
-
打包项目
- 指令配置
// packgae.json { "scripts": { "build": "webpack" } }- 说明
-
如上打包会按照 webpack4.X 默认打包机制 进行打包
-
后续文章会讲解 如何自定义打包
-
- 项目根目录下,终端执行
npm run build即可打包项目,输出到 根目录的dist文件夹
六、配置 资源路径
1. 解决 项目 中的路径问题
-
loader:url-loader、file-loader
解决项目中的路径问题(不限于 css)
让 webpack 识别 图片、视频、字体 等资源文件
-
url-loader 是 file-loader 的一个超集
低版本的 url-loader 中封装了 file-loader,url-loader 的运行 不会依赖file-loader
高版本的 url-loader 在使用时,需要额外安装 file-loader
-
url-loader 的 file-loader 区别
-
url-loader
解决项目中的路径问题
将 小体积的资源 转成 base64
让 webpack 识别 资源文件
-
file-loader
解决项目中的路径问题
让 webpack 识别 资源文件
-
-
file-loader 原理浅析
众所周知,webpack 会将各个模块打包成一个文件,最终我们样式中的 url 路径是相对入口html页面的,而不是相对于原始css文件所在的路径,这就会导致图片引入失败
file-loader可以解析项目中的url(不限于css),会根据配置 将图片拷贝到相应的路径,打包时会根据规则修改引入路径
-
安装
npm i url-loader@1.1.2 file-loader@3.0.1 -D -
配置
// webpack.config.js 文件 module.exports = { module: { rules: [{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 8192, // 文件体积小于 8192kb 时,将被转为 base64 资源 name: '[name].[ext]', outputPath: 'static/assets/' // 资源 输出路径 } }] }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, use: [{ loader: 'url-loader', options: { name: '[name].[ext]', outputPath: 'static/assets/' // 资源 输出路径 } }] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [{ loader: 'url-loader', options: { name: '[name].[ext]', outputPath: 'static/assets/' // 资源 输出路径 } }] }] } }; -
说明
-
以配置中
options.outputPath为例,资源将被输出到 根目录下static/assets文件夹中
2. 解决 html 中的路径问题
-
loader:html-withimg-loader
解决 html 中的路径问题,如
img标签的路径问题webpack 建议所有图片都使用背景图的方式,所以默认情况下 在html中使用
img标签,会显示路径错误 -
安装
npm i html-withimg-loader@0.1.16 -D -
配置
// webpack.config.js 文件 module.exports = { module: { rules: [{ test: /\.(htm|html)$/, use:[{ loader: 'html-withimg-loader' }] }] } };
七、配置 css相关
1. 识别 css
-
loader: css-loader style-loader
webpack 默认只识别JS文件,要解析打包css 必须安装相应的loader
-
安装
npm i style-loader@0.23.1 css-loader@2.1.0 -D -
配置
// webpack.config.js 文件 module.exports = { module: { rules: [{ test:/\.css$/, use: ['style-loader','css-loader'] }] } };
2. 识别 scss
-
loader 相关: sass-loader、node-sass
作为css预编译语言,需要 相应的loader进行解析
-
安装
npm i node-sass@4.11.0 sass-loader@7.1.0 -D -
配置
// webpack.config.js 文件 module.exports = { module: { relus: [{ test: /\.scss$/, use: ['style-loader','css-loader','sass-loader'] // 编译顺序从右往左 }] } };
3. 识别 less
-
loader 相关: less-loader、less
作为css预编译语言,需要 相应的loader进行解析
-
安装
npm i less@3.9.0 less-loader@4.1.0 -D -
配置
// webpack.config.js 文件 module.exports = { module: { relus: [{ test: /\.less$/, use: ['style-loader','css-loader','less-loader'] // 编译顺序从右往左 }] } };
4. 自动添加 css3属性前缀
-
loader 相关: postcss-loader、autoprefixer
针对css3新增的属性,并不是所有浏览器都支持
为兼容不同内核的浏览器,增加属性前缀(与内核相对应)
-webkit, -ms, -o, -moz -
安装
npm i postcss-loader@3.0.0 autoprefixer@9.4.4 -D -
配置
// 项目根目录新建 文件postcss.config.js,其中配置如下 module.exports = { plugins: [ require('autoprefixer')({ "browsers": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] }) ] };// webpack.config.js 文件 // 给 css文件 中的css3属性自动 加属性前缀 module.exports = { module: { rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] }] } };// webpack.config.js 文件 // 给 scss文件 中的css3属性自动 加属性前缀 module.exports = { module: { rules: [{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] // 编译顺序从右往左 }] } };// webpack.config.js 文件 // 给 css文件 中的less属性自动 加属性前缀 module.exports = { module: { rules: [{ test: /\.less$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] // 编译顺序从右往左 }] } };
5. 分离 css
-
插件:mini-css-extract-plugin
webpack 认为css应该被打包到JS中,以减少HTTP请求次数
但有的开发团队,要求 抽离css单独打包
-
安装
npm i mini-css-extract-plugin@0.5.0 -D -
配置
// webpack.config.js 文件,抽离css const MinicssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { module: { rules: [{ test: /\.css$/, use: [MinicssExtractPlugin.loader, 'css-loader'] }] }, plugins: [ new MinicssExtractPlugin({ filename: "static/css/[name].[hash:7].css" }) ] }// webpack.config.js 文件,抽离scss const MinicssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { module: { rules: [{ test: /\.scss$/, use: [MinicssExtractPlugin.loader, 'css-loader', 'sass-loader'] }] }, plugins: [ // 添加一处即可 new MinicssExtractPlugin({ filename: "static/css/[name].[hash:7].css" }) ] }// webpack.config.js 文件,抽离less const MinicssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { module: { rules: [{ test: /\.less$/, use: [MinicssExtractPlugin.loader, 'css-loader', 'less-loader'] }] }, plugins: [ // 添加一处即可 new MinicssExtractPlugin({ filename: "static/css/[name].[hash:7].css" }) ] } -
解决 css抽离后导致的路径问题
很容易将 css抽离出来,但是抽离出来的css中属性 引用路径并不对(原因浅析:打包后分离出来的css 和 html 不在同一级目录下)
解决方案:配置资源文件的输出路径(相对路径 改成 绝对路径)
// webpack.config.js 配置文件 let publicPath = ''; const isProduction = false; // 是否是生产环境 if (!isProduction) { publicPath = 'http://localhost:3000/static/assets'; } else { // 将 publicPath 设置为线上发布地址 } module.exports = { // loader 相关配置 module: { rules: [{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 8192, // 文件体积小于 8192kb 时,将被转为 base64 资源 name: '[name].[ext]', outputPath: 'static/assets/', // 资源 输出路径 publicPath } }] }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, use: [{ loader: 'url-loader', options: { name: '[name].[ext]', outputPath: 'static/assets/', // 资源 输出路径 publicPath } }] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [{ loader: 'url-loader', options: { name: '[name].[ext]', outputPath: 'static/assets/', // 资源 输出路径 publicPath } }] }] } };
6. 压缩 分离后的css
-
插件:optimize-css-assets-webpack-plugin
即使是生产模式下,分离后的css不会被压缩
使用此插件对css进行压缩处理
-
安装
npm i optimize-css-assets-webpack-plugin@5.0.1 -D -
配置
// webpack.config.js 文件 const Optimizecss = require('optimize-css-assets-webpack-plugin'); module.exports = { plugins: [ new Optimizecss() ] }
7. 净化 分离后的css
-
插件:purifycss-webpack、purify-css
对于页面中没有使用到的css,打包时可以通过此插件进行清除
限制:仅限于 清除分离后的css文件中 无用的样式
-
安装
npm i purifycss-webpack@0.7.0 purify-css@1.2.5 -D -
配置
// webpack.config.js 文件 const glob = require('glob'); const PurifycssPlugin = require("purifycss-webpack"); module.exports = { plugins: [ new PurifycssPlugin({ paths: glob.sync(path.join(__dirname, 'src/*.html')), }) ] };
八、配置 JS相关
1. babel 转换
-
概述
-
浏览器对 JavaScript 新语法、API、扩展语言的识别能力不同
-
babel 就是 JavaScript 语法编译器 之一
-
主要将 ECMAScript 2015+ 的JS代码转换成 低版本浏览器可识别的 JS 代码
-
将 JSX、TypeScript 等JS扩展语言 转换成 浏览器可识别的原生 JS
-
-
-
安装
npm i babel-loader@8.0.5 @babel/core@7.2.2 @babel/preset-env@7.2.3 @babel/plugin-transform-runtime@7.2.0 @babel/runtime@7.2.0 babel-plugin-transform-remove-console@6.9.4 @babel/plugin-syntax-dynamic-import@7.2.0 -D -
配置
下面是 babel 7+ | babel-loader 8+ 的相关配置
-
方式一:将 babel 的配置项抽离到 .babelrc 文件中(推荐)
// webpack.config.js 文件 const path = require('path'); module.exports = { module: { rules: [{ test: /\.js$/, use: ['babel-loader'], exclude: /node_modules/, // 排除不要加载的文件夹 include: path.resolve(__dirname, 'src') // 指定需要加载的文件夹 }] } };// .babelrc 文件中 配置 { "presets": [ [ "@babel/preset-env", // 根据 preset-env 标准进行转换 { "modules": false // 不转换模块类型 } ] ], "plugins": [ "@babel/plugin-transform-runtime", // 来处理全局函数和优化babel编译 "transform-remove-console" // 打包时 移除 console 相关(开发环境下 不需要配置) ], "comments": false // 打包时 移除脚本中的注释 } -
方式二:直接在 webpack 配置项中 配置(不推荐)
// webpack.config.js 文件 const path = require('path'); module.exports = { module: { rules: [{ test: /\.js$/, use: [{ loader: 'babel-loader', options: { { presets: [ [ "@babel/preset-env", // 根据 preset-env 标准进行转换 { "modules": false // 不转换模块类型 } ] ], plugins: [ "@babel/plugin-transform-runtime", // 来处理全局函数和优化babel编译 "transform-remove-console" // 打包时 移除 console 相关 ], comments: false // 打包时 移除脚本中的注释 } } }], exclude: /node_modules/, // 排除不要加载的文件夹 include: path.resolve(__dirname, 'src') // 指定需要加载的文件夹 }] } };
-
-
说明
2. 压缩 JS
-
webpack4.X 在
production模式下,自动压缩JS,所以通常情况下 项目中单独配置插件压缩JS的场景不多了 -
如下两个插件,可以压缩JS
九、webpack 配置文件
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MinicssExtractPlugin = require("mini-css-extract-plugin");
const Optimizecss = require('optimize-css-assets-webpack-plugin');
const glob = require('glob');
const PurifycssPlugin = require("purifycss-webpack");
let publicPath = '';
const isProduction = false; // 是否是生产环境
if (!isProduction) {
publicPath = 'http://localhost:3000/static/assets';
} else {
// 将 publicPath 设置为线上发布地址
}
module.exports = {
mode: 'development',
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'), // 打包后项目 输出到项目根目录下 dist 文件夹
filename: '[name].js' // 输出的 入口JS文件名称
},
// loader 相关配置
module: {
rules: [{
test: /\.(htm|html)$/,
use:[{
loader: 'html-withimg-loader'
}]
}, {
test: /\.css$/,
use: [MinicssExtractPlugin.loader, 'css-loader']
}, {
test: /\.scss$/,
use: [MinicssExtractPlugin.loader, 'css-loader', 'sass-loader']
}, {
test: /\.less$/,
use: [MinicssExtractPlugin.loader, 'css-loader', 'less-loader']
}, {
test: /\.js$/,
use: ['babel-loader'],
exclude: /node_modules/, // 排除不要加载的文件夹
include: path.resolve(__dirname, 'src') // 指定需要加载的文件夹
}, {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192, // 文件体积小于 8192kb 时,将被转为 base64 资源
name: '[name].[ext]',
outputPath: 'static/assets/',
publicPath
}
}]
}, {
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'static/assets/' // 资源 输出路径
}
}]
}, {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'static/assets/' // 资源 输出路径
}
}]
}]
},
// 插件 相关配置
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 文件名; 默认是index.html
template: './src/index.html' // 指定模板html文件
}),
// 分离 css
new MinicssExtractPlugin({
filename: "static/css/[name].[hash:7].css"
}),
// 压缩分离后的 css
new Optimizecss(),
// 净化 css
new PurifycssPlugin({
paths: glob.sync(path.join(__dirname, 'src/*.html')),
})
],
devServer:{
index: 'index.html', // 服务器启动的页面(同 html-webpack-plugin 中 filename 选项); 默认值为 index.html
host: 'localhost', // 指定host; 默认 localhost
port: 3000, // 指定端口号; 默认 8080
open: true, // 启动本地服务后,自动打开页面
compress: true, // 是否启用 gzip 压缩
overlay: true, // 编译器错误或警告时, 在浏览器中显示全屏覆盖; 默认false
progress: true, // 是否将运行进度输出到控制台; 默认 false
contentBase: path.resolve(__dirname, 'dist'), // 告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要
// 精简 终端输出(本地运行时)
stats: {
modules: false,
children: false,
chunks: false,
chunkModules: false
}
}
};