目录
(一) Webpack 概述
Webpack: 是一个现代的JavaScript应用的静态模块打包器, 这是Webpack官方的解释.在这句话中提到两个关键字:
-
模块: 在JavaScript发展初期就是为了实现简单的页面交互逻辑, 但随着前端技术不断更新、迭代, CPU、浏览器性能得到了极大的提升, 导致前端页面逻辑复杂, 代码日益膨胀. 此时就会考虑使用模块化规范去管理代码:
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
- 模块化规范: CommomJS、ES6、AMD、CMD
- Webpack其中一个核心: 让开发者尽可能用模块化开发, 并且会帮助我们处理模块间的依赖关系, 更甚的是: 不仅仅是JS文件, CSS、图片、JSON文件都会当做模块来使用
-
打包: Webpack帮助项目模块化, 并且处理模块间的各种复杂关系后, 就会对项目中各种资源模块进行打包合成一个或多个包. 在打包的过程中, 还可以对资源进行处理, 比如压缩图片, 将scss转换成css, 将ES6语法转成ES5语法, 将TypeScript转成JavaScript等等操作
(二) Webpack 基本使用
Webpack使用依赖着node环境, 而node环境运行需要各种依赖的包, 为了简化手动管理包的成本, 诞生npm工具(node package manager 软件包管理工具).
1. node 安装
node下载链接: https://nodejs.org/zh-cn/download/
查看安装的node版本: cmd中输入命令 node -v
2. Webpack 安装
全局安装webpack: npm install webpack@3.6.0 -g
查看安装的webpack版本: webpack --version
局部安装webpack: 在项目文件目录下执行: npm install webpack@3.6.0 --save-dev (开发时依赖, 运行时不依赖webpack)
- 在终端上直接执行webpack命令, 使用的是全局安装的webpack
- 当在 package.json 中定义了scripts时, 其中包含了webpack命令, 那么此时使用的是局部webpack
3. webpack 简单使用
对模块化的js文件打包, 新建文件目录:
main.js: 模块文件入口, 此模块不会依赖其他模块, 只会导入其他模块. Webpack会对入口文件打包, 且自动处理模块间的依赖关系
// 使用CommonJs的模块化规范: 导入
const {sum, mul} = require('./mathUtils.js')
// 使用ES6的模块化规范: 导入
import {name, age, height} from './info'
console.log(sum(10, 20))
console.log(mul(10, 20))
console.log(name)
console.log(age)
console.log(height)
mathUtils.js: 数学工具模块
function sum(num1, num2) {
return num1 + num2
}
function mul(num1, num2) {
return num1 * num2
}
// 使用CommonJs的模块化规范: 导出
module.exports = {
sum,
mul
}
info.js: 信息模块
const name = "zhang san"
const age = 22
const height = 1.88
// 使用ES6的模块化规范: 导出
export {name, age, height}
对 main.js 模块入口文件打包: 终端进入到项目目录下, 执行打包命令
webpack 要打包的(入口)模块文件路径 打包后生成文件的存储路径
webpack ./src/main.js ./dist/bundle.js
inde.html: 引入打包后生成的js文件
<body>
<script src="./dist/bundle.js"></script>
</body>
(三) webpack 配置文件
webpack 配置文件分为两种: webpack.config.js 和 package.json, 简化打包代码
在项目文件夹目录下新建webpack.config.js, 并添加js内容
const path = require('path') // 动态获取文件的绝对路径需要借助node语法, path对象从node包中导入, 必须先执行 npm init, 会在当前目录下生成package.json文件
module.exports = {
entry: './src/main.js', // entry 打包的入口文件: 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
output: { // output: 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件
path: path.resolve(__dirname, 'dist'), // 打包后文件存储绝对路径
filename: 'bundle.js' // 打包后文件名称
}
}
此时, 可以直接用命令 webpack 打包, 无需指定入口和出口文件
在package.json 文件的sripts脚本中, 可以将 任意命令(npm run build) 映射成 webpack命令, 终端直接执行npm run build命令, 相当于执行了 webpack命令.
还有一点, 在终端使用webpack命令操作都是全局webpack, 使用脚本执行映射的命令, 会优选选用局部webpack.
局部安装webpack: 在项目文件目录下执行:
npm install webpack@3.6.0 --save-dev (开发时依赖, 运行时不依赖webpack)
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack" // 将 npm run build 映射成 webpack命令
},
"author": "",
"license": "ISC"
}
(四) loader
loader: loader是一种打包方案, 用于对模块的源代码进行转换.
webpack 默认只会对js代码进行打包处理, 对其他文件(css, png…)是无法打包的. 但可以通过给webpack扩展对应的loader, 可以实现: 对css、图片打包处理, 也包括一些高级的将ES6转成ES5代码, 将TypeScript转成JavaSciprt, 将scss、less转成css、将.jsx、.vue文件转成js文件等等
loader使用
- 通过npm安装需要使用的loader, 可通过官网查询对应的loader: https://www.webpackjs.com/loaders/
- 在webpack.config.js中的module关键字下进行配置
1. loader-css 文件处理
-
在scr下创建css文件夹, 添加normall.css文件
body { background-color: red; }
-
在入口main.js文件引入(依赖)
// 使用CommonJs的模块化规范: 导入(依赖)css文件 require('./css/normal.css')
-
安装style-loader(将模块的导出作为样式添加到 DOM 中)、css-loader(解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码)
npm install style-loader --save-dev npm install --save-dev css-loader
-
在webpack.config.js中的module关键字下进行配置
module.exports = { module: { rules: [ { test: /\.css$/, /* css-loader 只负责jiangcss文件进行加载 style-loader 只负责将样式添加到DOM中 使用多个loader时, 是从右向左读取的顺序 */ use: [ 'style-loader', 'css-loader' ] } ] } }
-
重新打包运行
2. loader-图片文件处理
- 修改css样式(normal.css)
body { background: url('../img/small.jpg'); }
- 在入口main.js文件引入(依赖)
- 安装 url-loader
npm install --save-dev url-loader
- 在webpack.config.js中的module.rules添加配置
{ test: /\.(png|jpg|gif)$/, use: [{ loader: 'url-loader', options: { // 当加载的图片, 小于limit时, 会将图片编译成base64字符串形式 // 当加载的图片, 大于limit时, 需要使用file-loader模块进行加载 limit: 16000, // 打包后文件存储路径/[图片原名称].[取hash值前8位].[扩展名] (大于limit时,才会生效) name: 'img/[name].[hash:8].[ext]' } }] }
- 重新编译
图片(文件)字节数大于limit时, 需要安装新的loder: file-loader
npm install --save-dev file-loader
使用 file-loader打包, 会生成一个打包后的文件, 且需要存储到dis/name(上文配置的name), 同时还需要修改webpack.config.js
output: {
path:path.resolve(__dirname, 'dist'), // 打包后文件存储绝对路径
filename: 'bundle.js', // 打包后文件名称
publicPath: 'dist/' // 输出解析文件的目录,指定资源文件引用的目录
},
3. loader-ES6转ES5
webpack打包生成的bundle.js中, 默认的打包方式不会将ES6语法转换成ES5语法
有些浏览器是不支持ES6的语法的, 因此, 我们希望webpack打包过程中将ES6语法转换成ES5语法, 需要借助 babel-loader加载器
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
{
test: /\.js$/,
// 排除 node_modules, bower_components的js文件
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
(五) Webpack集成Vuejs
安装vuejs的依赖
npm install vue --save // 开发时依赖, 运行时也依赖
在main.js 导入Vue的依赖, 会在node_modules文件中查找
// 使用ES6的模块化规范: 导入vue, 在node_modules文件中查找依赖
import Vue from 'vue'
const app = new Vue({
el: '#app',
data() {
return {
message: 'Hello, Webpack!!'
}
}
})
在index.html中 创建挂彩元素(template)
<div id="app">
<h3>{{message}}</h3>
</div>
<script src="./dist/bundle.js"></script>
此时重新编译运行, 控制台报错:
产生这个原因的错误是因为: Vue最终构建发布版时, 构建了两个版本
- 运行时版本(runtime-noly): 在运行时版本中, 项目代码中不能有任何的template属性, 无法编译
- 编译版本(runtime-compiler): 在编译版本中, 能支持并编译 template属性
修改webpack.config.js, 指定Vue构建版本 (与entry、output、module属性并列)
resolve: {
alias: {
// 指定vue构建版本为编译版本, 当引入Vue依赖时, 会去 node_modules/vue/dist/vue.esm.js 这个文件地址查找
'vue$': 'vue/dist/vue.esm.js'
}
}
重新编译
Webpack集成Vue终极使用方案: 使用.vue文件开发
npm安装 vue-loader(加载vue) 和 vue-template-compiler(vue模板编译)
npm install vue-loader vue-template-compiler --save-dev
在webpack.config.js中的module关键字下进行配置
{
test: /\.vue$/,
user: {
loader: 'vue-loader'
}
}
在webpack.config.js中引入Vue加载器插件
const VueLoaderPlugin = require('vue-loader/lib/plugin') // 从node_modules文件夹中引入vue加载器插件
module.exports = {
...,
resolve: {
extensions: ['.js', '.css', '.vue'], // 设置导入此文件时, 可以省略后缀名
alias: {
'vue$': 'vue/dist/vue.esm.js' // 指定vue构建版本为编译版本
}
},
plugins: [
new VueLoaderPlugin() // 创建vue加载器对象
]
}
(六) Plugin
webpack中的插件, 就是对webpack现有功能的各种扩展, 解决 loader 无法实现的功能. 如: 打包优化, 文件压缩等等
plugin 与 loader 区别:
- loader: 主要用于转换某些类型的模块, 是一个加载, 转换器
- plugin: 插件, 它是对webpack本身的扩展, 是一个扩展器
plugin 使用过程
- 通过npm安装需要使用的plugins(某些插件已内置)
- 在webpack.config.js中导入plugin插件
- 在webpack.config.js中的 plugins中配置插件
1. BannerPlugin
BannerPlugin: webpack自带插件, 为打包的文件bundle.js添加版权声明
在webpack.config.js中导入plugin插件 和 在plugins中配置插件
const webpack = require('webpack')
module.exports = {
...,
plugins: [
new webpack.BannerPlugin('版权最终归 又十七 所有')
]
}
2. html-webpack-plugin
html-webpack-plugin: 在打包后的文件夹(dist)下, 生成一个index.html文件, 并且将打包的js文件, 自动通过script标签插入到body中
安装html-webpack-plugin插件
npm install html-webpack-plugin@3.2.0 --save-dev
在webpack.config.js中导入plugin插件 和 在plugins中配置插件
const HtmlWebpackPlugin = requrie('html-webpack-plugin')
...
output: {
...,
// publicPath: 'dist/' html文件已在dist文件夹中
},
plugins: [
... ,
new HtmlWebpackPlugin({
template: 'index.html' // 使用index.html作为模板(index.html已删除打包后的js文件引入)
})
]
3. uglifyjs-webpack-plugin
uglifyjs-webpack-plugin: 插件对打包js文件进行压缩(丑化)
安装uglifyjs-webpack-plugin插件
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
在webpack.config.js中导入plugin插件 和 在plugins中配置插件
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
plugins: [
... ,
new UglifyjsWebpackPlugin ()
]
(七) Webpack 搭建本地服务器
webpack提供了一个可选的本地开发务器, 它基于node.js搭建, 内部使用express框架, 可以实现让自动刷新显示我们修改后的结果
安装webpack-dev-server模块
npm install webpack-dev-server@2.9.3 --save-dev
在webpack.config.js中的module关键字下进行配置
module.exports = {
... ,
devServer: {
contentBase: './dist', // 为哪一个文件夹提供本地服务(默认根文件夹)
port: 8080, // 默认使用8080端口
inline: true // 页面实时刷新
}
}
在package.json中的script脚本添加映射命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server --open"
},
执行终端执行 npm run dev 命令, 会自动打开浏览器页面, 本地服务器搭建完毕
在此之前我们对webpack.config.js 添加很多配置: entry(入口)、output(出口)、module(loader加载器配置)、pugins(插件)、resolve()、devserver(服务器) 等等. 但有些配置是开发时需要(本地服务器…), 有些配置是编译打包时需要(压缩js文件插件…), 没有做具体的区分
webpack配置文件分离
安装webpack-merge依赖
npm install webpack-merge --save-dev
拆分配置文件, 配置文件同一放入build文件夹
prod.confg.js
const webpackMerge = require('webpack-merge') // 导入webpack配置文件合并的依赖
const baseConfig = require('./base.config') // 导入base.config.js 文件依赖
const uglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin') // 导入打包压缩js文件插件
// 合并 base.config.js 配置文件
module.exports = webpackMerge(baseConfig, {
plugins: [
new uglifyjsWebpackPlugin()
]
})
dev.confg.js
const webpackMerge = require('webpack-merge') // 导入webpack配置文件合并的依赖
const baseConfig = require('./base.config') // 导入base.config.js 文件依赖
module.exports = webpackMerge(baseConfig, {
devServer: {
contentBase: './dist', // 为哪一个文件夹提供本地服务(默认根文件夹)
port: 9090, // 默认使用8080端口
inline: true // 页面实时刷新
}
})
package.json中scripts脚本命令中指定webpack配置文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/prod.config.js", // 指定prod.config.js 配置文件
"dev": "webpack-dev-server --open --config ./build/dev.config.js" // // 指定dev.config.js 配置文件
}