webpack核心概念(系列一)
### webpack 介绍 * 什么是webpack<https://www.webpackjs.com/> * Webpack是一个模块打包器(bundler)。 * 在Webpack看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理 * 它将根据模块的依赖关系进行静态分析,生成对应的静态资源 * 五个核心概念 * Entry:入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。 * Output:output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件 * Loader:loader 让 webpack 能够去处理那些非 JavaScript 文件 * Plugins:插件则可以用于执行范围更广的任务。例如:打包优化、压缩, * Mode:模式,有生产模式 production (压缩)和开发模式 development * 理解 Loader * Webpack 本身只能加载 JS/JSON 模块,如果要加载其他类型的文件(模块),就需要使用对应的loader 进行转换/加载 * Loader 本身也是运行在 node.js 环境中的 JavaScript 模块 * loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 less-loader。 * 理解 Plugins * 插件可以完成一些loader不能完成的功能。 * 插件的使用一般是在 webpack 的配置信息 plugins 选项中指定。 * 配置文件(默认) * webpack.config.js : 是一个node模块,返回一个 json 格式的配置信息对象
1. import ... from 模块导入
npm init 包名(初始化), 自动生成一个package.json文件,
npm i webpack webpack-cli --save-dev (局部安装)
npx webpack index.js (webpack将index.js文件编译打包),自动生成dist文件夹--》main.js的打包文件
index.js
// ES Moudule 模块引入方式 import Header from './header.js'; import Sidebar from './sidebar.js'; new Header(); new Sidebar(); new Content();
header.js
function Header() { var dom = document.getElementById('root'); var header = document.createElement('div'); header.innerText = 'header'; dom.append(header); } exports.default Header;
sidebar.js
function Sidebar() { var dom = document.getElementById('root'); var sidebar = document.createElement('div'); sidebar.innerText = 'sidebar'; dom.append(sidebar); } exports.default Sidebar;
index.html, 引入打包之后的js文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>这是最原始的网页开发</title> </head> <body> <p>这是我们的网页内容</p> <div id='root'></div> <script src='./dist/main.js'></script> </body> </html>
此时页面可以注册显示
注;export ...from 是es6语法,浏览器不支持,需要通过webpack解析成浏览器支持的语法.
webpack模块打包工具,将所有的模块打包到一个文件
webapck支持也cmmonJs模块引入规范
// webpack 模块打包工具 // js 模块打包工具 -> // import Header from './header.js'; // import Sidebar from './sidebar.js'; // import Content from './content.js'; var Header = require('./header.js'); var Sidebar = require('./sidebar.js'); new Header(); new Sidebar();
function Header() { var dom = document.getElementById('root'); var header = document.createElement('div'); header.innerText = 'header'; dom.append(header); } //导出 module.exports = Header;
2.webapck安装方法
npm init -y 初始化包,自动生成一个package.json文件
npm install webpack webpack-cli -g //全局安装,作为指令使用
npm install webpack webpack-cli -D //本地安装,作为本地依赖使用
注;不建议全局安装webpack, 每个项目的webpack版本都不一样,会发生错乱
卸载。 npm uninstall webpack webpack-cli -g
webpack -v 版本(全局查询)
npx webpack -v(局部查询)
npm i webpack@4.2.5 webpack-cli -D 安装特定版本
3. webpack配置文件webpack.config.js
3.1. 配置出入口,此时运行打包命令, npx webpack,即可打包, 后面不需追加入口文件,因为,webpack配置了入口和出口。打包后的文件
dist-->bundle.js
//node内置核心模块,用来设置路径。 const path = require('path'); //只能使用 CommonJS 规范暴露 module.exports = { // 入口文件配置 entry: './src/index.js', // 输出配置 output: { // 输出文件名(打包文件名) filename: 'bundle.js', //输出文件路径配置,dist文件夹,打包之后的路径dist-->bundle.js path: path.resolve(__dirname, 'dist') } }
第二种的打包命令,在package.json中的script配置命令, 执行npm run bundle(底层执行了npx webpack), 即可打包文件了
{ "name": "lesson", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "bundle": "webpack" }, "author": "", "license": "ISC", "devDependencies": { "webpack-cli": "^3.1.2" }, "dependencies": { "webpack": "^4.25.1" } }
3.2, 打包模式,
webpack默认是配置production环境,他会压缩bundle.js打包文件, 开发环境不会
//node内置核心模块,用来设置路径。 const path = require('path'); //只能使用 CommonJS 规范暴露 module.exports = { // 开发环境 mode: 'development', // 入口文件配置 entry: './src/index.js', // 输出配置 output: { // 输出文件名(打包文件名) filename: 'bundle.js', //输出文件路径配置,dist文件夹,打包之后的路径dist-->bundle.js path: path.resolve(__dirname, 'dist') } }
* webpack能够编译打包 js 和 json 文件 * 能将 es6 的模块化语法转换成浏览器能识别的语法 不能编译打包 css、img 等文件
打包样式文件中的图片资源
图片文件 webpack 不能解析,需要借助 url-loader编译解析
-
两张资源图片:
-
小图, 小于8kb: src/images/vue.png
-
大图, 大于8kb: src/images/react.jpg
-
-
.react {
width: 200px;
height: 200px;
background: url('../images/react.png') no-repeat;
background-size: cover;
}
.vue {
width: 200px;
height: 200px;
background: url('../images/vue.png') no-repeat;
background-size: cover;
} -
安装 loader
> npm install file-loader url-loader --save-dev
补充:url-loader是对象file-loader的上层封装,使用时需配合file-loader使用。
-
webpack.config.js 配置 loader
module.exports = {
.
.
.
module: {
rules: [
.
.
.
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192, // 8kb以下的图片会 base64 处理
outputPath: 'images/', // 图片打包的文件夹 dist/images/xxx.png
name: '[hash:8].[ext]', // 修改文件名称和后缀
}
}
},
]
}
} -
运行指令 npm run bundle
注;如果图片小于8kb,图片会在打包文件bundle.js中引入(以base64方式引入),如果大于8kb,会在打包文件dist-->images--xxx.png中出现,然后在bundle.js以路劲方式引入
打包 less 资源
less 文件 webpack 不能解析,需要借助 loader 编译解析,使用步骤如下:
-
创建less文件
-
src/css/test1.less
-
src/css/test2.less
-
入口app.js文件
//引入两个 less 文件
import '../css/test1.less';
import '../css/test2.less';
-
安装 loader
npm install css-loader style-loader less-loader less --save-dev
-
webpack.config.js 配置 loader
module.exports = { . . . module:{ rules:[ { test:/\.less$/, // 检查文件是否以.less结尾(检查是否是less文件) use:[ // 数组中loader执行是从下到上,从右到左顺序执行 'style-loader', // 创建style标签,添加上js中的css代码 'css-loader', // 将css以commonjs方式整合到js文件中 'less-loader' , // 将less文件解析成css文件
'postcss-loader' //添加样式将入厂商样式,兼容性,可以不添加
] } ] }, } -
运行指令 npm run bundle
注;对于postcss-loader需要安装, npm i postcss-loader,同时需要安装postcss的一个插件autoprefixer, npm i autoprefixer,并且要配置postcss.config.js文件
module.exports = { plugins: [ require('autoprefixer') ] }
style-loader在html中style添加样式, css-loader分析css的各个文件引入关系,合并一个css文件
{ test: /\.less$/, use: [ 'style-loader', { loader: 'css-loader', options: { // 存在多个引用css关系,同样先执行下面两个loader(postcss-loader,sass-loader) importLoaders: 2, // 开启样式模块化,样式不会冲突 modules: true } }, 'less-loader', 'postcss-loader' ] }
如果index.less 引入了home.less, @import './home.less', 可以配置importLoaders属性,让webpack从同样先执行下面两个loader(postcss-loader,sass-loader)
打包字体资源
字体文件需要借助 file-loader 编译解析,以 iconfont 为例,下载一个项目
-
将字体文件保存在
src/fonts
目录下
-
src/fonts/iconfont.eot
-
src/fonts/iconfont.svg
-
src/fonts/iconfont.ttf
-
src/fonts/iconfont.woff
-
src/fonts/iconfont.woff2
-
创建 src/css/iconfont.less 并将 iconfont 的 css 样式粘到 less 文件中,并修改字体路径
@font-face {
font-family: 'iconfont';
src: url('../fonts/iconfont.eot');
src: url('../fonts/iconfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/iconfont.woff2') format('woff2'),
url('../fonts/iconfont.woff') format('woff'),
url('../fonts/iconfont.ttf') format('truetype'),
url('../fonts/iconfont.svg#iconfont') format('svg');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-
修改
src/index.html
<span class="iconfont"></span>
-
配置 loader
module.exports = {
.
.
.
module: {
rules: [
.
.
.
{
test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/, // 处理字体文件
loader: 'file-loader',
options: {
outputPath: 'fonts',
name: '[name]_[hash:8].[ext]'
}
}
]
}
} -
运行指令 npm run bundle
打包 HTML 文件
HTML 文件不能直接被 webpack 解析,需要借助 HtmlWebpackPlugin
插件编译解析
-
在 src 目录下创建 index.html 文件,==注意不要在 HTML 中引入任何 CSS 和 JS 文件==
-
安装插件
> npm install html-webpack-plugin --save-dev
-
webpack.config.js 修改配置
// 插件都需要手动引入
const HtmlWebpackPlugin = require('html-webpack-plugin');
.
.
module.exports = {
.
.
mode: 'development',
.
.
.
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 设置要编译的 HTML 源文件路径
})
]
} -
运行指令 npm run bundle
此时,dist-->index.html,自动生成了一个打包后的html文件,并且打包后的js自动引入了html中
如果我们需要修改
清除打包文件目录
每次打包生成了文件,都需要手动删除,引入插件 clean-webpack-plugin
帮助我们自动删除上一次生成的文件
-
安装插件
> npm install clean-webpack-plugin --save-dev
-
webpack.prod.js
引入插件//1. 引入插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
.
.
.
module.exports = {
.
.
.
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
//2. 配置插件
new CleanWebpackPlugin()
],
} -
运行指令 npm run bundle