Vue.js- webpack 详解
1.1 什么是Webpack?
从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具。
前端模块化
- 在ES6之前,我们要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发。
- 并且在通过模块化开发完成了项目后,还需要处理模块间的各种依赖,并且将其进行整合打包。
- 而webpack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。
- 而且不仅仅是JavaScript文件,CSS、图片、json文件等等在webpack中都可以被当做模块来使用。
打包
就是将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。
并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。
webpack安装
安装webpack首先需要安装Node.js,Node.js自带了软件包管理工具npm。NPM官方的管理的包都是从 http://npmjs.com下载的,但是这个网站在国内速度很慢。这里推荐使用淘宝 NPM 镜像 http://npm.taobao.org/ ,淘宝 NPM 镜像是一个完整npmjs.com 镜像,同步频率目前为 10分钟一次,以保证尽量与官方服务同步。
设置镜像和存储地址:
# 由于npm代码仓库的服务器在国外,由于Great Firewall的缘故,这时可以使用淘宝的npm代码仓库,通过npm安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装成功后,可以通过以下命令查看cnpm版本:
cnpm -v
#设置npm下载包时保存在本地的地址(建议英文目录),通过cnpm来操作下载速度会得到很大提升,但包的版本不一定是最新的。
cnpm config set prefix "E:\\Develop\\repo_npm"
#查看cnpm配置信息
cnpm config list
查看自己的node版本
node -v
全局安装webpack(这里我先指定版本号3.6.0,因为vue cli2依赖该版本)
cnpm install webpack@3.6.0 -g
查看webpack版本
webpack --version
1.2 Webpack 初体验
项目目录
文件和文件夹解析:
- dist文件夹:用于存放之后打包的文件。
- src文件夹:用于存放我们写的源文件
- main.js:项目的入口文件。具体内容查看下面详情。
- mathUtils.js:定义了一些数学工具函数,可以在其他地方引用,并且使用。
- index.html:浏览器打开展示的首页html,package.json:通过npm init生成的,npm包管理的文件。
mathUtils.js
function add(num1, num2) {
return num1 + num2
}
function mul(num1, num2) {
return num1 * num2
}
// 模块导出
module.exports = {
add,
mul
}
info.js
// 导出模块
export const name = 'GuardWhy';
export const age = 18;
export const height = 1.71
main.js
// 1. 使用commonjs的模块化导入
const {add, mul} = require('./mathUtils')
// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));
// 2.使用es6的模块化规范
import {name, age, height} from "./info";
console.log(name);
console.log(age);
console.log(height);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack基本使用</title>
</head>
<body>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>
webpack的指令打包
webpack src/main.js dist/bundle.js
使用打包后的文件
打包后会在dist文件下,生成一个bundle.js文件
bundle.js文件,是webpack处理了项目直接文件依赖后生成的一个js文件,只需要将这个js文件在index.html中引入即可。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack基本使用</title>
</head>
<body>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>
执行结果
1.3 webpack的配置
项目目录
配置文件
webpack.config.js
// 1.获得路径
const path = require('path');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js'
},
}
局部安装webpack
因为一个项目往往依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题。
所以通常一个项目,都有自己局部的webpack。
cnpm install webpack@3.6.0 --save-dev
配置package.json
打开项目的命令所在位置,执行npm init
命令,可得到package.json文件,可以在package.json的scripts中定义自己的执行脚本。
{
"name": "guardwhy",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "guardwhy",
"license": "ISC",
"devDependencies": {
"webpack": "^3.6.0"
},
"dependencies": {},
"description": ""
}
当执行npm run build
命令时候会直接生成bundle.js。
1.4 什么是loader?
webpack用来做什么呢?
在之前的实例中,主要是用webpack来处理写的js代码,并且webpack会自动处理js之间相关的依赖。
在开发中不仅仅有基本的js代码处理,也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件。对于webpack本身的能力来说,对于这些转化是不支持的。那怎么办呢?给webpack扩展对应的loader就可以啦。
loader使用过程
步骤一:通过npm安装需要使用的loader。
步骤二:在webpack.config.js中的modules关键字下进行配置。
1.4.1 css文件处理
项目开发过程中,必然需要添加很多的样式,而样式往往写到一个单独的文件中。
在src目录中,创建一个css文件,其中创建一个normal.css文件,也可以重新组织文件的目录结构,将零散的js文件放在一个js文件夹中。
normal.css中的代码非常简单,就是将body设置为red。
body {
background-color: red;
}
但是,这个时候normal.css中的样式会生效吗?当然不会,因为压根就没有引用它。
webpack也不可能找到它,因为只有一个入口,webpack会从入口开始查找其他依赖的文件。
在入口文件中引用
main.js
// 1. 使用commonjs的模块化导入
const {add, mul} = require('./js/mathUtils')
// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));
// 2.使用es6的模块化规范
import {name, age, height} from "./js/info";
console.log(name);
console.log(age);
console.log(height);
// 依赖css文件
require('./css/normal.css')
执行 npm run build 命令后出现错误!!!
加载*.css文件和格式必须有对应的loader
文档目录: https://webpack.docschina.org/loaders/#styling
安装CSS-loader
cnpm install --save-dev css-loader@3.6.0
安装style-loader
cnpm install --save-dev style-loader@1.3.0
安装以后可以在package.json文件中查看到版本号。
配置webpack.config.js
// 1.获得路径
const path = require('path');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{ test: /\.css$/,
/*
css-loader只负责将css文件进行加载
style-loader负责将样式添加到DOM中
使用多个loader时, 是从右向左
*/
use: ['style-loader','css-loader']
}
]
}
}
执行npm run build命令,可能会出现以下的问题。
通过查看错误提示,发现会不会有可能是css-loader的版本太高了,所以把css-loader的版本由4.2.0改为了3.6.0!!!
执行结果
1.4.2 less文件处理
项目目录
在入口文件中引用
main.js
// 1. 使用commonjs的模块化导入
const {add, mul} = require('./js/mathUtils')
// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));
// 2.使用es6的模块化规范
import {name, age, height} from "./js/info";
console.log(name);
console.log(age);
console.log(height);
// 依赖css文件
require('./css/normal.css')
// 依赖less文件
require('./css/special.less')
document.write('<h3>kobe是mvp!!!</h3>')
加载*.less文件和格式必须有对应的loader
文档目录: https://webpack.docschina.org/loaders/#styling
安装less-loader
cnpm install less-loader@5.0.0 --save-dev
安装less
cnpm install less@3.13.1--save-dev
安装以后可以在package.json文件中查看到版本号。
配置webpack.config.js
// 1.获得路径
const path = require('path');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js'
},
module: {
rules: [
{ test: /\.css$/,
/*
css-loader只负责将css文件进行加载
style-loader负责将样式添加到DOM中
使用多个loader时, 是从右向左
*/
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
}
]
}
}
执行npm run build命令。
执行结果
1.4.3 图片文件处理
项目目录
normal.css中的样式
body {
background: url("../img/timg.jpg");
}
加载图片文件和格式必须有对应的loader
文档目录: https://webpack.docschina.org/loaders/#files
安装url-loader
cnpm install url-loader@2.0.0 --save-dev
安装file-loader
cnpm install file-loader@2.0.0 --save-dev
安装以后可以在package.json文件中查看到版本号。
配置webpack.config.js
// 1.获得路径
const path = require('path');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{ test: /\.css$/,
/*
css-loader只负责将css文件进行加载
style-loader负责将样式添加到DOM中
使用多个loader时, 是从右向左
*/
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 当加载的图片,小于limit时会将图片编译成base64字符串形式
//当加载的图片,大于limit时需要使用file-loader模块进行加载
limit: 13000,
name: 'img/[name].[hash:8].[ext]'
}
}
]
}
]
}
}
执行npm run build命令。
执行结果
1.4.4 ES6语法处理
果希望将ES6的语法转成ES5,那么就需要使用babel,而在webpack中,直接使用babel对应的loader就可以了。
安装babel-loader
cnpm install --save-dev babel-loader@7 babel-core babel-preset-es2015
安装以后可以在package.json文件中查看到版本号。
配置webpack.config.js
// 1.获得路径
const path = require('path');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{ test: /\.css$/,
/*
css-loader只负责将css文件进行加载
style-loader负责将样式添加到DOM中
使用多个loader时, 是从右向左
*/
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 13000,
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
}
}
重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法。
1.5 webpack配置Vue
1.5.1 引入vue.js
安装Vue,在实际项目中也会使用vue的,所以并不是开发时依赖。
cnpm install vue@2.5.11 --save
main.js
import Vue from 'vue'
new Vue({
el:'#app',
data:{
message:'hello Vue.js!!!'
}
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack配置Vue</title>
</head>
<body>
<div id = "app">
{{message}}
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>
执行npm run build 命令结果,报错!!!
解决方案修改webpack的配置
webpack.config.js
// 以下内容
resolve: {
// alias: 别名
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
执行结果
1.5.2 el和template区别
正常运行之后,来考虑另外一个问题
如果希望将data中的数据显示在界面中,就必须是修改index.html
但是html模板在之后的开发中,并不希望手动的来频繁修改。
定义template属性
在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例之后可以管理它其中的内容。
这里,可以将div元素中的{{message}}内容删掉,只保留一个基本的id为div的元素。
el和template模板的关系是什么呢?
知道el用于指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听等。
而如果Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。
这样做之后就不需要在以后的开发中再次操作index.html,只需要在template中写入对应的标签即可。
代码示例
main.js
import Vue from 'vue'
new Vue({
el:'#app',
template:`
<div>
<h3>{{message}}</h3>
<button @click= "btnClick">按钮</button>
<h3>{{name}}</h3>
</div>
`,
data:{
message:'hello Vue.js!!!',
name: 'guardwhy'
},
methods:{
btnClick(){
}
}
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack配置Vue</title>
</head>
<body>
<div id = "app">
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>
执行结果
1.5.3 Vue组件化开发
项目目录
安装vue-loader和vue-template-compiler
cnpm install vue-loader vue-template-compiler --save-dev
安装以后可以在package.json文件中查看到版本号。
修改webpack.config.js的配置文件
// 1.获得路径
const path = require('path');
// 引入webpack
const webpack = require('webpack');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
// alias: 别名
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
}
代码示例
main.js
import Vue from 'vue'
import App from "./vue/App.vue"
new Vue({
el:'#app',
template:'<App/>',
components:{
App
}
})
App.vue
<template>
<div>
<h3 class="title">{{message}}</h3>
<button @click="btnClick">按钮</button>
<h3>{{name}}</h3>
<Cpn></Cpn>
</div>
</template>
<script>
// 引入组件
import Cpn from './Cpn'
export default {
name: "App",
// 注册Cpn组件
components: {
Cpn
},
data(){
return {
message: 'hello webpack!!!!',
name: 'guardwhy'
}
},
methods: {
btnClick(){
}
}
}
</script>
<style scoped>
.title {
color: green;
}
</style>
Cpn.vue
<template>
<div>
<h3>我是NBA球星</h3>
<p>我是三分王,我是Curry</p>
<h3>{{name}}</h3>
</div>
</template>
<script>
export default {
name: "Cpn",
data(){
return{
name: 'hello Vue.js!!!'
}
}
}
</script>
<style scoped>
</style>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack配置Vue</title>
</head>
<body>
<div id = "app">
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>
执行命令npm run build
,执行成功!!!
1.6 认识plugin
plugin是什么?
- plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
- webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。
loader和plugin区别
- loader主要用于转换某些类型的模块,它是一个转换器。
- plugin是插件,它是对webpack本身的扩展,是一个扩展器。
plugin的使用过程:
- 步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)。
- 步骤二:在webpack.config.js中的plugins中配置插件。
1.6.1 打包html的plugin
HtmlWebpackPlugin插件具体作用
自动生成一个index.html文件(可以指定模板来生成)。
将打包的js文件,自动通过script标签插入到body中。
安装HtmlWebpackPlugin插件
cnpm install html-webpack-plugin --save-dev
安装以后可以在package.json文件中查看到版本号。
修改webpack.config.js文件
// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
// publicPath: 'dist/'
},
plugins: [
// 添加插件
new HtmlWebpackPlugin({
template: 'index.html'
}),
]
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack配置Vue</title>
</head>
<body>
<div id = "app">
</div>
</body>
</html>
使用命令 npm run build 执行操作,发现报错!!!
解决方案!!!
HtmlWebpackPlugin插件版本太高了,将HtmlWebpackPlugin版本设置为2.0.0
终端执行命令
cnpm install
操作结果
1.6.2 js压缩的Plugin
安装uglifyjs-webpack-plugin插件
cnpm install uglifyjs-webpack-plugin@1.1.1 --save-dev
修改webpack.config.js文件
// 添加压缩js插件
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
// 支持导出
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
// publicPath: 'dist/'
},
plugins: [
new UglifyjsWebpackPlugin()
]
}