webpack
vue项目2种部署方式:
1.前后端分离:vue项目打包,将打包项目放在tomcat/nginx下,浏览器直接访问index.html
2.前后端不分离:自己的html中引入打包成的js,使用<script type="text/x-template" id="task_handle_template">,作为1中的index.html
命令:
#生成package.json文件
npm init
#下载包(下载package.json中的包,每次package.json中有新的改动使用下面命令下载,如果package.json中没有相应的包,使用npm install xx,也会更新package.json)
npm install
vue项目流程
-
当我们看vue项目时,先从package.json入手,看scripts,当执行
npm run test
,输出“Error...”,当执行npm run start
时会执行“webpack --watch ”命令 -
npm run server和npm run build会找到对应的webpack.xx.config.js文件,打包入口到出口文件夹
一.前端模块化
前端模块化规范:AMD、CMD、CommonJS、ES6
webpack其中一个核心就是让我们进行模块化开发,且帮助处理模块间的关系
模块化的两个核心:导出和导入
#导出(a.js中,return就相当于模块导出):
var modelA = function({
return a
})
#导入(b.js中引用modelA)
console.log(modelA);
一.CommonJS
commonjs(规范)导出,webpack配置文件中有common.js,如果只是单单在代码中写module.exports和require,浏览器是无法识别的,webpack会将其转为浏览器可识别的。
module.exports = {
flag:true, //键值对
test(a,b){
return a+b
}
}
commonjs导入
let {test,flag} = require("moduleA") //require()参数为模块路径
等同于:
let _ma = require("moduleA")
let test = _ma.test;
let flag = _ma.flag;
二.ES6
同级目录下创建a.js、b.js、index.html(每个js相当于一个模块,要用export、import导入导出,需要在html中引入js文件,且type为module,这是ES6写法)
a.js(导出方式)
let a = 1;
let b = 2;
function sum(a,b){
return a+b;
}
export {a,b.sum}
//导出方式二:export let num1=2 #导入 import {num1} from "a.js"
//导出方式三(导出类):
export class Person(){} #导入 import {Person} from 'a.js'
//导出默认:export default sum #导入可用别名:import xx from 'a.js' 此处可不用{}大括号
index.html
<script src="./a.js" type="module"></script>
<script src="./b.js" type="module"></script>
b.js(导入方式)
import {a} from "./a.js" // from的路径应该是需要在html中引入的
二..webpack
webpack自动处理js之间的依赖,将ES6转为ES5、TypeScript转为ES5、less转为css、Vue转为js文件等,也就是转为当前浏览器可识别的格式,但是webpack本身不支持,需要使用loader
一.安装
1.依赖node环境(自带npm:node包管理工具,相当于pip)
2.全局安装webpack(先指定版本3.6.0,vue cli2依赖该版本,vue-cli2可见webpack配置信息,vue-cli3屏蔽了很多webpack的配置信息)
npm install webpack@3.6.0 -g
3.局部安装webpack(会在项目文件夹下生成node_modules文件夹)
npm install webpack@3.6.0 --save-dev
4.查看webpack版本
webpack --version
为什么全局安装之后,还需局部安装?
在终端执行webpack命令后,使用的是全局安装的webpack
当在package.json中定义了script时,其中包含了webpack命令,使用的是局部webpack
二.使用
每个项目中都有src、dist文件夹
src:自己开发使用
main.js/index.js:主入口(相当于c++中main函数)
dist:打包成功生成的(将index.html和打包成功的js结合发布)
项目文件(运行index.html,一般会引用src中的模块化文件,进入console,可见到打印内容):
//aa.js
function sum(a,v){
return a+v;
}
export {sum}
//main.js
import {sum} from '../src/aa.js'
console.log(sum(1,2));
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="./src/aa.js" type="module"></script>
<script src="./src/main.js" type="module"></script>
</body>
</html>
运行打包命令(打包main.js即可),将其打包到dist文件夹下
webpack ./src/main.js ./dist/bundle.js //webpack 入口 出口
打包成功后可看到dist文件夹下生成bundle.js,之后index.html中
<script src="./dist/bundle.js"></script>
三.配置文件
1.package.json
该文件由命令npm init
初始化生成,命令npm install
会下载package.json中的包,如果package.json中有模块A,node_modules文件夹没有,会下载到node_modules文件夹下,如果node_modules下有,package.json中没有,也会在配置文件中默认添加上。
文件初始化内容:
{
"name": "webpacktest",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
2.webpack.config.js
有了package.json基础上,在项目根目录下新建webpack.config.js(遵循commonJs模块化规范),注名字不能错,使用命令 webpack
会找当前文件夹中的webpack.config.js,将entry中的文件打包到output的所配置的dist文件夹下的build.js
const path = require('path') //会先从package.json中找到path包,如果找不到,去全局找
module.export = {
entry:'./src/main.js' //入口
output:{ //出口
path:path.resolve(__dirname,"dist") //使用resolve拼接dist的绝对路径
filename:"build.js"
}
}
3.node_modules
node_modules是本地node包存储的路径,当使用命令npm install webpack@3.6.0 --save-dev
时,会初始化node_modules文件夹。
4.总结
1.使用 webpack
命令打包时,会找到webpack.config.js中的入口和出口
2.使用 npm run xx
命令时,会从package.json中找scripts中的键为'xx',执行其对应的值。命令如:npm run build
。
3.package.json中的scripts的脚本在执行时,会优先从本地的node_modules/bin下找到相应的模块,如果没有,会从全局中找
4.命令行执行的命令都是从全局中找,文件中的命令是先从本地找
1.修改package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"build":"webpack" #此处配置会优先找本地的webpack:node_modules/bin/文件夹下
},
四.loader
在模块化开发时,如果在main.js中直接引用css(require("./x.css")),webpack打包是会出错误的,单使用webpack是无法处理css、less文件的,需要使用loader,webpack和loader都是开发编译时使用
官方文档:https://www.webpackjs.com/concepts/
1.使用方法
1.npm install对应的loader
2.在webpack.config.js的modules中使用其loader
2.style-loader/css-loader
#main.css
body{
background-color: red;
}
#main.js
import {sum} from './aa.js'
import '../css/main.css' #引入main.css
console.log(sum(1,2));
#webpack.config.js(output同级)
module: {
rules: [
{
test: /\.css$/, #匹配所有的css文件(这些css文件都是main.js中导入的)
use: [ #使用的module也是从npm_modules
{ loader: 'style-loader' }, #style-loader起到打包后渲染作用
{
loader: 'css-loader', #css-loader起到打包时导入css作用
options: {
modules: true
}
}
]
}
]
}
#index.html(还是使用打包后的build.js)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--<script src="./src/aa.js" type="module"></script>-->
<!--<script src="./src/main.js" type="module"></script>-->
<script src="./dist/build.js" type="module"></script>
</body>
</html>
下载相应的css包(如果下载后版本过大,修改package.json中版本,然后再执行npm install命令)
npm install --save-dev css-loader
npm install --save-dev style-loader
前提工作完成后,使用npm run build命令进行打包
2.less-loader
参考:https://www.webpackjs.com/loaders/less-loader/
Less是一门css预处理语言,扩展了css语言,增加了变量、Mixin、函数等特性。less可以运行在node或者浏览器端
#src下新建main1.less
@fontSize:50px;
@fontColor:orange;
body{
font-size: @fontSize;
color: @fontColor;
}
#main.js
import {sum} from './aa.js'
import '../css/main.css'
import '../css/main1.less'
console.log(sum(1,2));
#index.html
<body>
<script src="./dist/build.js" type="module"></script>
<p>你好</p>
</body>
</html>
#webpack.config.js(rules的第二个字典)
{
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打包
3.url-loader
按照2中,只改变main.css\webpack.config.js
图片小于limit限制时 npm install --save-dev url-loader
body{
/*background-color: red;*/
background: url("../imgs/s.jpg");
}
webpack.config.js
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
//图片小于limit限制时,导入的图片资源会以base64形式显示
//图片大于limit限制时,需要引入file-loader,且会将图片打包到dist文件夹下
limit: 25600,
}
}
]
}
图片大于limit时,需要使用file-loader,先 npm install --save-dev file-loader
main.css
body{
/*background-color: red;*/
background: url("../imgs/big.jpg");
}
webpack.config.js
output:{ //出口
path:path.resolve(__dirname,"dist"), //dist的绝对路径
filename:"build.js",
publicPath: "dist/" //打包成功后,main.css的url路径会默认添加dist/生成的文件
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 25600,
name:'img/[name].[hash:8].[ext]' //会在dist生成img文件夹,[]内是变量
}
}
]
}
4.babel
我们打包成功的dist下的js文件,还是ES6规范(const,let),并没有转为ES5,要想ES6->ES5,需要使用babel,babel也是一种loader,和上述用法相同,参考:https://www.webpackjs.com/loaders/babel-loader/ ,配置完之后重新命令npm run build
,此时看打包后的文件,已经是ES5规范
5.总结
1.所有的css/less等文件都是在main.js主入口函数中引用的,可以使用ES6语法:import xx from xx ,或者commonJS中的require("xx")
五.webpack使用vue
1.安装
在项目中要使用vuejs,需要对其有所依赖(因后续生产环境也会用vue,所以不是安装开发时依赖,开发时依赖是save-dev)
npm install vue --save
2.演练
//main.js
import Vue from "vue" //会从node_modules中找到vue
const app = new Vue({ //在正式开发环境中不需要声明变量app
el:"#div1",
data:{
message:"hello world"
}
})
//index.html
<div id="div1">{{message}}</div>
以上代码打包运行,会出现如下错误,意思是runtime-only模式下不能编译带有template的vue,因为index.html中的div是template
然后先来介绍两个版本:
runtime-only:代码中,不可以有任何的template
runtime-compile:代码中可以有template,因为有compile可以编译template
解决错误方式(webpack.config.js中添加resolve,vue.esm.js中含有能够编译template的方法):
module.exports = {
module: {
xxx
},
resolve:{
alias:{
'vue$':"vue/dist/vue.esm.js"
}
}
}
3.el和template的关系
当一个vue实例中既有el,又有template时候,template会将el替换,这样的好处是我们不用再改动html代码
//main.js
import Vue from "vue"
const app = new Vue({
el:"#div1",
template:`
<div>
<h2>template中内容</h2>
</div>
`,
data:{
message:"hello world"
}
});
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="div1">{{message}}</div> //{{message}}将不会显示
<script src="./dist/bundle.js"></script>
</body>
</html>
4.组件.vue使用
1.使用方式
//main.js
import Vue from "vue"
import app from "./vuecon/math.vue"
// const app = {
// template:`
// <div>
// <h2>template中内容{{message}}</h2>
// <button @click="fun">点击按钮</button>
// </div>
// `,
// data(){
// return {
// message:"xxxx"
// }
// },
// methods:{
// fun(){
// console.log("按钮点击了")
// }
// }
// }
new Vue({
el:"#div1",
template:"<app/>", //此处写法<app/>也就是引用组件app
components:{
app
}
});
新建vue模块(和上面注释部分替换):分为三部分:
- template:将注释部分的template内容复制,注意必须要有根节点
- script
- style:本组件的样式
<template>
<div>
<h2>template中内容{{message}}</h2>
<button @click="fun">点击按钮</button>
</div>
</template>
<script>
export default {
name: "math",
data(){ //子组件的数据
return {
message:"xxxx"
}
},
methods:{
fun(){
console.log("按钮点击了")
}
}
}
</script>
<style scoped>
h2{
color: burlywood;
}
</style>
2.编译出错解决方法
当引用vue组件后编译时,会出现错误,需要加载vue对应的loader,如果编译再报错(提示缺少组件),可以降低vue-loader的组件.
npm install vue-loader vue-template-compiler --save-dev
webpack.config.js中配置
module: {
rules: [
{
test: /\.vue$/i,
use: ['vue-loader'],
},
],
},
六.搭建本地服务
搭建本地服务之后不用每次都打包运行,可以这样理解,contentBase提供本地服务的文件夹就是要打包后的js文件所在文件夹,本地服务就是将要打包成的js文件(没有真正打包)放在缓存区中,这样每次启动服务重新打包。
- 搭建本地服务前提:index.html复制一份要放在dist文件夹下,当执行命令
npm run dev
会开启服务
七.配置文件抽离
将webpack.config.js分为三部分:
const path = require('path') //会先从package.json中找到path包,如果找不到,去全局找
const webpack = require("webpack")
module.exports = {
entry:'./src/index.js', //入口
output:{ //出口
path:path.resolve(__dirname,"dist"), //使用resolve拼接dist的绝对路径
filename:"build.js"
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
},
},
plugins:[
new webpack.BannerPlugin("最终版权归xx所有")
],
devServer:{
contentBase:'./dist',
inline:true,
}
}
-
base.config.js
const path = require('path') //会先从package.json中找到path包,如果找不到,去全局找 const webpack = require("webpack") module.exports = { entry:'./src/index.js', //入口 output:{ //出口 path:path.resolve(__dirname,"dist"), //使用resolve拼接dist的绝对路径 filename:"build.js" }, resolve: { alias: { 'vue$': 'vue/dist/vue.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js' }, } }
-
prod.config.js
module.exports = { plugins:[ new webpack.BannerPlugin("最终版权归xx所有") ], }
-
dev.config.js
module.exports = { devServer:{ contentBase:'./dist', inline:true, } }