grunt/gulp:他们的核心是Task
什么时候用grunt/gulp
grunt/gulp和webpack有什么不同
webpack是模块化打包工具
webpack为了正常运行,必须依赖node环境
node环境为了能够正常执行很多代码,必须其中包含各种依赖的包
这时需要使用npm工具(node packages manager)
安装webpack首先需要安装node.js,node.js自带了软件包管理工具 npm
查看node版本:
node -v
全局安装webpack
npm install webpack@3.6.0 -g
局部安装webpack
npm install webpack@3.6.0 --save-dev
为什么需要使用webpack?
有时候我们需要把我们的代码打包,发送给服务器,发布项目。此前,模块化代码的导入、导出方式有CommonJS,ES6。但是使用CommonJS直接导入、导出时,浏览器不能直接解析,需要借助webpack将我们的代码进行打包
这里以一个简单的例子来介绍代码打包
文件结构如下:
index.html:是项目的入口文件
dist:是用来存放打包后的代码的文件(刚开始是没有东西的,这个目录是我打包后的)
src:主要用来编写各种主要项目代码
main.js:进行文件的导入
mathUtils:编写代码,进行代码导出
mathUtils.js中的代码:
function sum(a, b) {
return a + b;
}
function mul(a, b) {
return a * b;
}
function sub(a, b) {
return a - b;
}
//1.使用CommonJS的方式进行打包
module.exports = {
sum,
mul,
sub
}
main.js中的代码:
//啊啊啊,文件的路径不要写错啦啦啦!!! 当前文件夹 ./
const {sum, mul, sub} = require('./mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
然后可以使用webpack进行打包啦
将终端目录切换到当前项目的目录,使用 cd 指令
输入命令:
webpack ./src/main.js -o ./dist/bundle.js
翻译一下:将当前文件夹src中的main.js文件,打包输出为当前文件夹dist下的bundle.js文件中
报错了怎么办
很正常的,不要着急
打包后的文件结构:
打包完之后,就可以在index.html中引入打包后的文件了。
index.html中的代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<script src="dist/bundle.js/main.js">script>
body>
html>
显示效果:
注意:这个过程中自己犯的错误
module: 你又又又写错了,都看了不下3遍了,你又又又写成了modlue。module:组件,模块的意思,真的无语死了
还可以使用webpack对ES6中的导入、导出进行打包。
例子接上一个,只是做了一个小扩展
文件结构:
export const name = 'YiBo';
export const age = 18;
export const height = 1.82
src中 main.js 中添加后的代码为:
const {sum, mul, sub} = require('./mathUtils.js');
import {name, age, height} from './info';
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
console.log(name);
console.log(age);
console.log(height);
弄完之后,还需要对webpack进行一次打包:
webpack ./src/main.js -o ./dist/bundle.js
代码运行后显示效果:
why要进行webpack.config.js的配置
在使用webpack进行打包的过程中,我们发现每次使用webpack都需要使用很多的代码,eg: webpack ./src/main.js -o ./dist/bundle.js
,这样使用真的真的很不方便,需要一种简写的方式运行webpack,eg: 直接输入webpack就可以自动打包,所以,这时,需要进行webpack.config.js文件的配置。
在webpack.config.js中进行配置时,我们需要导入node包中的path模块,为了保证模块的正常导入,我们需要执行:npm init
代码,进行相应的配置,生成package.json
文件
生成的package.json文件为:
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
进行webpack.config.js文件配置:
需要在项目中新建一个webpack.config.js文件
最终webpack.config.js中的代码为:
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
弄好之后,在终端中使用webpack
指令,即可完成打包。
显示效果:(注意:这里复用的基本上都是上一个例子的代码)
补充:发现在使用 webpack ./src/main.js -o ./dist/bundle.js
进行打包时,发现最终生成的是bundle.js文件夹,文件夹里面有main.js文件,而这个main.js文件就是打包好的那个文件。而使用webpack.config.js文件之后,使用webpack
进行打包后,生成的就是正常的bundle.js文件
为了更加方便的使用webpack,可以对webpack再做一层映射
在package.json中进行
在“script”中添加了"build" : “webpack” 内容
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC"
}
在终端中调用npm run build
是可以正常打包的。
why要做这一层映射,有什么好处
这样做之后,每次执行这个命令(npm run build),其实它是先用的是本地的webpack。
所以,需要在项目中安装一下本地的webpack,这里安装的是开发时的版本
npm install webpack@3.6.0 --save-dev
package.json文件中的内容:
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.6.0"
}
}
文件目录结构:
简单介绍一下loader:
loader是webpack中非常核心的概念。
loader的使用过程:
怎么好点学习 loader 有关内容:
why需要进行css配置
由于在开发过程中,我们会有很多的css文件,如果一个个的引入就太麻烦了,这时候我们可以用webpack对所有的css文件进行打包,这样的话,是比较符合实际过程的开发的。
但是进行css配置时,需要安装相应的 loader
安装 css-loader、style-loader
css-loader:解析css文件后,使用import加载,并且返回CSS代码
style-loader:将模块的导出作为样式添加到DOM中
官方给出的安装代码
npm install --save-dev css-loader
npm install style-loader --save-dev
注意:演示案例基本上是基于js模块化打包的案例进行讲解的(就是上一个的案例)
安装完之后,可以去package.json文件中查看安装的版本
安装完成后,进行配置:在webpack.config.js中配置
webpack.config.js中的代码:
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个loader时,是从右向左读的
use: ['style-loader', 'css-loader']
}
]
}
}
案例中的目录结构:
normal.css中的代码:
body {
background-color: #42b983;
}
main.js中的代码:(入口文件)
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css')
运行文件:npm run build
版本问题:不兼容,版本回退
//安装style-loader:
npm install --save-dev style-loader@1.2.1
//安装css-loader:
npm install --save-dev css-loader@1.0.1
再次打包: npm run build
运行index.html文件: 界面发生改变
在实际开发过程中,我们也需要对less文件进行模块化打包
在官网上查找安装 less-loader 的代码
npm install --save-dev less-loader less
在webpack.config.js文件中进行配置
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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
}]
}
]
}
}
案例中的目录结构:
special.less中的代码:
@fontSize: 50px;
@fontColor: white;
body {
font-size: @fontSize;
color: @fontColor;
}
main.js中的代码:(入口文件)
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
进行打包: npm run build
报错!!! 安装版本太高
重新安装less-loader
npm install --save-dev less-loader@4.1.0 less@3.9.0
安装完成之后,再重新打包一次
显示效果:
注意:每次改变代码之后,都需要使用 npm run build,重新打包一次
在实际的开发过程中,我们也需要对图片对象进行打包
为了让图片能够正常的打包,我们需要安装对应的loader文件。
在官网上查找安装 url-loader 的代码
npm install --save-dev url-loader
可以在package.json文件中查看安装的url-loader安装的版本。
在webpack.config.js文件中进行配置
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192 //这个是8k的限制:1024*8=8192
}
}
]
}
]
}
}
文件的目录结构:
在normal.css中引入图片文件:图片大小小于8kb
body {
/*background-color: #42b983;*/
background: url(../img/one.jpg); /*在css文件中引用图片对象*/
}
进行打包: npm run build
报错!!!
原因:安装的url-loader版本不兼容
重新安装 url-loader
npm install [email protected] --save-dev
安装完成之后,使用npm run build
再进行一次打包
打包完成:
运行index.html,显示效果:
此时图片是以base64的方式保存的
做一点改变:在normal.css中引入图片文件:图片大小 大于8kb
body {
/*background-color: #42b983;*/
background: url(../img/two.jpg); /*在css文件中引用图片对象*/
}
直接使用 npm run build
进行打包,报错!!!
需要安装 file-loader
官网查找安装方式:会报错,版本兼容性太差
npm install file-loader --save-dev
需要安装低版本的 file-loader
npm install [email protected] --save-dev
再进行打包:npm run build
打包成功,运行 index.html,不显示效果
原因分析:图片的路径地址不对,打包生成的图片在dist文件夹中,而我们引用的url是在img文件夹中,会出现图片文件找不到的错误。
此时文件的目录结构为:
为了让图片的路径为dist文件夹中的图片路径,需要更改webpack.config.js中的配置
publicPath: ‘/dist’
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/' //为了使打包后的图片文件能够正常显示
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192 //这个是8k的限制:1024*8=8192
}
}
]
}
]
}
}
再次打包:npm run build
运行 index.html
如果同时有多张图片都打包到dist中,就显得太乱了,我们希望它可以打包到dist/img文件下
此时,需要在webpack.config.js中进行配置
name: 'img/[name].[hash:8].[ext]'
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
}
]
}
}
再进行打包:npm run build
图片正常显示,文件的目录结构为:
why需要ES6转ES5
我们开发的各种项目文件是需要运行到各大浏览器中去的,但是大部分的浏览器都支持ES5,为了能够使代码能够正常的运行,我们需要将ES6代码文件转为ES5。
安装babel-loader、babel-core、babel-preset-es2015
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
在webpack.config.js中进行相关的配置
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
}
}
进行打包:npm run build
此时,打包的bundle.js文件中没有ES6相关的语法,转为了ES5。
使用 npm 安装Vue
这里安装的是vue2.多的版本
npm install vue@2.6.14 --save
在main.js中引入vue:
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
// 5.使用vue进行开发
import Vue from 'vue'
const app = new Vue({
el: '#app',
data: {
message: 'hello webpack'
}
})
在index.html中编写相应代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">
<h2>{{message}}h2>
div>
<script src="dist/bundle.js">script>
body>
html>
进行打包:npm run build
运行index.html文件,报错!!!
简单介绍一下:runtime-only、runtime-compiler
why出现这个错误
在这个过程中,会将el:‘#app’,挂载的这个app当成一个template模板,无法正常编译这个模板,就会报错。
在webpack.config.js中更改配置
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
}
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
}
}
再进行打包:npm run build
运行 index.html 文件
在Vue中使用 template 的话,它会替换掉 el 中的内容
why要使用vue中的 template
在开发项目时,如果只有一个index.html文件,那么将要展示的对象都定义在这个index.html界面中,显得界面凌乱,并且也是不可取的,所以我们可以把这些内容写在template中,并且 template 会替换掉 el 中的内容
index.html中的代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">div>
<script src="dist/bundle.js">script>
body>
html>
main.js中的代码:
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
// 5.使用vue进行开发
import Vue from 'vue'
new Vue({
el: '#app',
template:
`
{{message}}
`,
data: {
message: 'hello webpack'
}
})
进行打包:npm run build
运行index.html文件
why需要进行代码抽离
如前所述,当我们编写代码一直都在Vue实例中编写,对于template来说,如果编写的代码过多,就显得很难看,很不好,所以对于一些代码文件进行分离是十分有必要的。
将vue实例中进行DOM显示操作的代码抽取到组件中,将组件注册到vue实例的template中,即可完成代码的部分抽离
main.js中的文件:
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
// 5.使用vue进行开发
import Vue from 'vue'
const App = {
template:
`
{{message}}
`,
data() {
return {
message: 'hello webpack'
}
},
methods: {
btnClick() {
console.log('您点击了我一下!!!');
}
}
}
new Vue({
el: '#app',
template:' ',
components: {
App
}
})
index.html中的文件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">div>
<script src="dist/bundle.js">script>
body>
html>
进行文件打包:npm run build
运行index.html文件
这样抽离后,代码整体还并不算简便,我们发现抽取的组件是一个对象,所以,我们可以使用ES6中的export 和 import的方式进行下一步的抽取
我们可以建立一个vue文件夹,在文件夹中 new一个app.js文件,这个文件用来进行组件代码的编写
文件的目录结构为:
app.js 中的代码: 其实就是上一个组件中的代码 export
export default {
template:
`
{{message}}
`,
data() {
return {
message: 'hello webpack'
}
},
methods: {
btnClick() {
console.log('您点击了我一下!!!');
}
}
}
main.js中的代码: import
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
// 5.使用vue进行开发
import Vue from 'vue'
import App from './vue/app'
new Vue({
el: '#app',
template:' ',
components: {
App
}
})
进行打包: npm run build
运行 index.html 文件
这些分离出来的代码也行,但是我们发现组件中的模板和 js 代码也没有进行分离,所以,我们可以进行下一步的代码抽取,将 template 模板和 js 代码进行分离
需要在vue文件夹中新建一个App.vue文件,在App.vue 文件中完成 template 模板和js的代码分离
App.vue中的代码为:
<template>
<div>
<h2 class="title">{{message}}</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
message: 'hello webpack'
}
},
methods: {
btnClick() {
console.log('您点击了我一下!!!');
}
}
}
</script>
<style scoped>
.title {
color: green;
}
</style>
main.js中的文件为:
// 1.使用commonJS模块化规范
const {sum, mul, sub} = require('./js/mathUtils.js');
console.log(sum(20, 30));
console.log(mul(40, 50));
console.log(sub(60, 20));
//2.使用ES6中的模块化规范
import {name, age, height} from './js/info';
console.log(name);
console.log(age);
console.log(height);
// 3.依赖css文件
require('./css/normal.css');
// 4.依赖css文件
require('./css/special.less');
document.writeln('今天也要好好加油呀!
')
// 5.使用vue进行开发
import Vue from 'vue'
import App from './vue/App.vue' //导入了App.vue文件
new Vue({
el: '#app',
template:' ',
components: {
App
}
})
进行打包:npm run build
运行index.html文件 报错!!!
原因分析:它不能解析.vue文件,需要合适的 loader 辅助解析
注意:如果在导入的时候使用的是import App from './vue/App'
,那么它不会报错,但是也不会显示任何的样式效果,因为没有暴露出.vue后缀名。
安装 vue-loader、vue-template-compiler
npm install --save-dev vue-loader vue-template-compiler
在webpack.config.js中进行配置
{
test: /\.vue$/,
use: ['vue-loader']
}
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
}
}
应该是版本过高,出现的兼容性问题
在package.json文件中更改 vue-loader的版本:"vue-loader": "^13.0.5"
package.json文件:
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"css-loader": "^1.0.1",
"file-loader": "^3.0.1",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"style-loader": "^1.2.1",
"url-loader": "^1.1.2",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.6.14",
"webpack": "^3.6.0"
},
"dependencies": {
"vue": "^2.6.14"
}
}
再进行安装 npm install
更改完成后,进行打包:npm run build
运行index.html
使用vue文件进行代码的抽离之后,我们便可以使用.vue文件进行组件化开发了。
这里新建一个Cpn.vue文件,进行组件代码的编写
文件的目录结构为:
Cpn.vue中的代码:
<template>
<div>
<h2>我是cpn的标题</h2>
<p>{{message}}</p>
</div>
</template>
<script>
export default {
name: "Cpn",
data() {
return {
message: "good luck for you"
}
}
}
</script>
<style scoped>
</style>
在App.vue中复用这个组件:
<template>
<div>
<h2 class="title">{{message}}</h2>
<button @click="btnClick">按钮</button>
<Cpn/>
<Cpn/>
</div>
</template>
<script>
import Cpn from './Cpn.vue'
export default {
name: "App",
data() {
return {
message: 'hello webpack'
}
},
methods: {
btnClick() {
console.log('您点击了我一下!!!');
}
},
components: {
Cpn
}
}
</script>
<style scoped>
.title {
color: green;
}
</style>
进行打包:npm run build
运行index.html代码
如果想省略后缀名还能够正常运行代码的话,需要在webpack.config.js中进行配置
resolve: {
extensions: ['.js', '.css', '.vue']
}
const path = require('path'); //导入node包中的path
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
}
}
可以将导入文件的.vue文件名省略
进行打包:npm run build
运行index.html,内容正常显示
plugin:插件的意思,通常是用于对现有的架构进行扩展。
loader 与 plugin的区别
plugin的使用过程:
why 需要使用pugin
我们打包完文件之后,可能需要进行一些说明信息,例如:此份代码是否开源,版权信息,一些开发说明信息等等,可以使用plugin进行说明
在webpack.config.js中配置plugin:
const webpack = require('webpack') //可直接导入,webpack中有对应的插件
module.exports = {
plugins: [
new webpack.BannerPlugin('最终版权归***所有')
]
}
const path = require('path'); //导入node包中的path
const webpack = require('webpack'); //导入webpack包
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
},
plugins: [
new webpack.BannerPlugin('最终版权归heng所有')
]
}
进行打包:npm run build
查看打包后的bundle.js文件
why需要使用 HtmlWebpackPlugin
当我们在开发项目的过程中,也需要将.html文件打包发送给服务器,此时就需要使用htmlWebpackPlugin插件进行打包。
HtmlWebpackPlugin插件的作用
安装HtmlWebpackPlugin插件
// 1.使用官网的方式安装: 后续会报错,版本太高
npm install html-webpack-plugin --save-dev
// 2.安装低版本的html-webpack-plugin
npm install html-webpack-plugin@3.2.0 --save-dev
在webpack.config.js中进行配置
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin()
]
const path = require('path'); //导入node包中的path
const webpack = require('webpack'); //导入webpack包
const HtmlWebpackPlugin = require('html-webpack-plugin'); //导入安装的包
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
},
plugins: [
new webpack.BannerPlugin('最终版权归heng所有'),
new HtmlWebpackPlugin()
]
}
进行打包:npm run build
打包前文件目录结构:
打包后文件目录结构:
包中的 index.html 文件
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack Apptitle>
head>
<body>
<script type="text/javascript" src="dist/bundle.js">script>body>
html>
src中的 index.html 文件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">div>
<script src="dist/bundle.js">script>
body>
html>
对比包中的 index.html 文件和 src 文件中的 html 文件,我们发现打包的 index.html还缺少 这些代码,所以,我们可以在生成index.html文件时,通过指定模板来解决这个问题。同时,通过打包后的文件目录结构,我们也可以看出,bundle.js 与 index.html在同一目录结构下,所以并不需要加上***dist/***这个路径了。所以,我们可以将webpack.config.js中的
publicPath: 'dist/'
的配置给删除。
在webpack.config.js中进行配置:
//1.删掉配置的 publicPath: 'dist/'
// publicPath: 'dist/'
//配置html模板
plugins: [
new webpack.BannerPlugin('最终版权归heng所有'),
new HtmlWebpackPlugin({
template: 'index.html' //在当前目录下查找index.html,所以,找的就是src中的index.html
})
]
src中的 index.html 文件中的内容
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">div>
body>
html>
进行打包: npm run build
包中的 index.html 文件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index.htmltitle>
head>
<body>
<div id="app">div>
<script type="text/javascript" src="bundle.js">script>body>
html>
使用 HtmlWebpackPlugin插件,可以将html文件打包,并且可将打包好的 js 文件插入到 打包的html文件中
why需要压缩、丑化 js代码
我们在使用 webpack 打包 js 文件时,其实打包后的 js 文件还是很大的,这不是我们想要的效果,我们需要将js代码压缩的小一点,这时可以使用uglifyjs-webpack- plugin插件来丑化代码。
安装 uglifyjs-webpack-plugin插件
// 1.安装低版本的插件
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
在webpack.config.js文件中进行配置
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
plugins: [
new UglifyJsPlugin()
]
const path = require('path'); //导入node包中的path
const webpack = require('webpack'); //导入webpack包
const HtmlWebpackPlugin = require('html-webpack-plugin'); //导入安装的包
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //导入丑化的包
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
// publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
},
plugins: [
new webpack.BannerPlugin('最终版权归heng所有'),
new HtmlWebpackPlugin({
template: 'index.html' //在当前目录下查找index.html,所以,找的就是src中的index.html
}),
new UglifyJsPlugin()
]
}
进行打包:npm run build
查看打包后的bundle.js文件:
why需要搭建本地服务器
我们在开发过程中,如果每一次更改一部分代码,都要使用npm run build
进行打包,这样做是很麻烦的,也不是我们希望的结果。所以我们可以在本地搭建一个服务器,每次更改代码都能直观的看到结果,如果需要发布项目,再进行最终的一个打包。
安装 webpack-dev-server
npm install --save-dev webpack-dev-server@2.9.1
在webpack.config.js文件中进行配置
配置属性介绍:
devServer: {
contentBase: './dist',
inline: true
}
在 package.json 文件中配置服务器运行的脚本
"dev": "webpack-dev-server"
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"css-loader": "^1.0.1",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"style-loader": "^1.2.1",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^1.1.2",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.6.14",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
},
"dependencies": {
"vue": "^2.6.14"
}
}
按住 ctrl 并点击链接,进入界面:
补充:如果希望使用npm run dev
之后,直接跳转到对应的页面中去的话,可以在package.json中更改配置:
"dev": "webpack-dev-server --open"
why需要进行配置文件的分离
当我们在webpack.config.js中配置一些文件时,其中有的文件是在开发时需要使用的,有的是在打包时需要的,如果将它们混淆在一起,也是不好的,所以,为了让代码结构更加清晰,我们需要进行配置文件的分离操作。
新建一个build文件夹,用来完成配置文件的分离的操作。在build文件夹中新建一个base.config.js,用来编写基础的配置;新建一个prod.config.js,用来编写生产时的配置;新建一个dev.config.js,用来编写开发时配置
文件的结构为:
思路:使用 base.config.js 和 prod.config.js 完成生产时依赖;使用 base.config.js 和 dev.config.js 完成开发时依赖
为了能使两个配置文件合并,需要安装webpack-merge
//1.直接安装,后续运行时会报错,安装的版本太高,不兼容
npm install webpack-merge --save-dev
//2.安装低版本的webpack-merge
npm install webpack-merge@4.1.5 --save-dev
在 prod.config.js 中将 prod.config.js 与 base.config.js 合并;在 dev.config.js 中将 dev.config.js 与 base.config.js 合并
prod.config.js中的代码:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //导入丑化的包
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');
module.exports = webpackMerge(baseConfig, {
plugins: [
new UglifyJsPlugin()
],
})
dev.config.js中的代码:
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');
module.exports = webpackMerge(baseConfig, {
devServer: {
contentBase: './dist',
inline: true
}
})
base.config.js中的代码
const path = require('path'); //导入node包中的path
const webpack = require('webpack'); //导入webpack包
const HtmlWebpackPlugin = require('html-webpack-plugin'); //导入安装的包
module.exports = {
entry: './src/main.js',
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
// publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
//1.css-loader只负责将css文件加载,是不负责解析的
//2.style-loader负责将样式添加到DOM中
//3.使用多个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: 8192, //这个是8k的限制:1024*8=8192
name: 'img/[name].[hash:8].[ext]' //生成的图片文件在img文件夹下,拥有自己的name,hash值8位,扩展名extension
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js' //在执行vue文件时,会使用vue.esm.js执行,这里可进行编译
}
},
plugins: [
new webpack.BannerPlugin('最终版权归heng所有'),
new HtmlWebpackPlugin({
template: 'index.html' //在当前目录下查找index.html,所以,找的就是src中的index.html
}),
],
}
删除 webpack.config.js代码
在 package.json 文件中重新指定webpack的运行路径
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
进行打包:npm run build
文件打包到了build文件夹下
why 会出现这样的情况
由于我们一开始是在webpack.config.js中配置base.config.js,其中路径为’dist’,即以webpack.config.js为标准,同级建立一个dist文件夹。所以,对于base.config.js来说,会在base.config.js同级的build文件夹下进行打包。为了解决这个问题,可以更改文件的路径:path: path.resolve(__dirname, '../dist')
在base.config.js中更改文件:
output: {
//需要动态获取路径,不然会报错, __dirname保存的是当前文件的路径
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
// publicPath: 'dist/'
},
进行打包:npm run build
打包后的文件目录结构为:
启动本地服务器:npm run dev