关于前端的工程化工具
grunt
- 资源打包
- 单元测试
gulp
- 流式操作工具
- 资源打包
webpack 【 主流 】
学习vue的过程肯定会接触到vue的单文件组件,进而接触到vue-cli(vue工程构建的脚手架工具),但是vue-cli创建的工程对初学者很不友好,vue init webpack-simple project-name创建的项目又太过简单和片面。
接下来我们从初始化到写配置再到添加loader和插件逐步构建一个可用的vue工程化环境,让初学者亲自搭建vue-cli之余还了解到webpack常用的一些配置项。
- 资源打包工具, 比如 js文件打包压缩 , img 打包压缩 。。。
- 可以自动解决模块化依赖问题
- es6模块化
创建工程
前提你已经安装了node、npm环境
mkdir project-vue
cd project-vue
npm init
//初始化设置都按enter默认就好,或者按你需要改
安装webpack到项目中
npm install --save-dev webpack
//啰嗦一下淘宝镜像设置
npm install -g cnpm –registry=https://registry.npm.taobao.org
创建webpack配置文件
webpack在运行时候会找到启用webpack命令目录下的webpack.config.js,所以要创建该文件到项目根目录下。
//webpack.config.jsconst path = require('path')
module.exports ={
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'dist'),
filename:"js/[name].js"
}
}
以上是最简单的模板,设置了入口文件(entry)和出口地址(output),这些有一点webpack基础的都知道,不了解的先去入门一下webpack的基础配置。而path函数则是node自带的路径相关的中间件,基本上整个项目就用到这样一个node的中间件,path就是用来做路径拼接返回一个路径字符串,可以简要看一下path。同时还要创建index.html和main.js文件,项目目录结构如下:
index.html
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<title>vue demo</title></head><body>
<div id="app">
</div>
<script src="./dist/js/main.js"></script></body></html>
main.js里面随便写点js就行
运行
webpack
这里有一份npm script的介绍,不用谢
npm run build
根目录下会多出一个dist文件夹里面放了打包好的文件。
引入一系列的依赖和loader
vue工程当然要安装vue依赖啦
npm install --save vue
vue-loader是必须的,vue-template-compiler是vue-loader必须的依赖
npm install --save-dev vue-loader vue-template-compiler
写现代的项目怎么可能不用到es6以上,来个es编译器loader
npm install --save-dev babel-core babel-loader
再来个css的加载器和转换器,style-loader会把css转成js,再贴到html的style标签上的哦~
npm install --save-dev css-loader style-loader
还有图片文件和字体文件的加载器,url-loader依赖于file-loader所以都要安装,url-loader会把小于限制的文件改成base64格式直接传入src里面,可以降低网络请求次数。而file-loader会自动帮我们添加文件名规则而且url地址一起跟着改变。
npm install --save-dev file-loader url-loader
以上的loader的配置下面开始简要讲解
loader配置项
每一种loader都对应着一种文件,我们匹配项目种的文件添加loader。
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry:{
app:'./src/main.js',
},
output:{
path:path.resolve(__dirname,'./dist'),
filename:"js/[name].js",
},
module:{
rules:[
{
test:/\.js$/, //用正则匹配文件,用require或者import引入的都会匹配到
loader:"babel-loader", //加载器名,就是上一步安装的loader
exclude:/node_modules/ //排除node_modules目录,我们不加载node模块中的js哦~
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
// 'postcss-loader'
]
//依次使用以上loader加载css文件,postcss-loader可以暂时不加,后面再深入修改webpack配置的时候再说用处
//
//也可以写成这样 loader:"style-loader!css-loader!postcss-loader"
},
{
test:/\.(png|jpe?j|gif|svg)(\?.*)?$/,
loader:'url-loader',
options:{
limit:10000,
name:'img/[name].[ext]?[hash]'
}
//图片文件大小小于limit的数值,就会被改写成base64直接填入url里面,
//不然会输出到dist/img目录下,[name]原文件名,[ext]原后缀,[hash]在url上加上一点哈希值避免缓存。
},
{
test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader:"url-loader",
options:{
limit:10000,
name:'fonts/[name].[ext]?[hash]'
}
//和上面一致
},
{
test:/\.vue$/,
loader:'vue-loader'
//这一个loader当然是vue项目必须的加载器啦,不加其他规则的话,
//简单的这样引入就可以了,vue-loader会把vue单文件直接转成js。
},
]
},
resolve:{
//引入路径是不用写对应的后缀名
extensions: ['.js', '.vue', '.json'],
//缩写扩展
alias:{
//正在使用的是vue的运行时版本,而此版本中的编译器时不可用的,我们需要把它切换成运行时 + 编译的版本
'vue$':'vue/dist/vue.esm.js',// 'vue/dist/vue.common.js' for webpack 1
//用@直接指引到src目录下,如:'./src/main'可以写成、'@/main'
'@': path.resolve(__dirname,'./src'),
}
},
}
开始使用.vue
main.js改成如下
import Vue from 'vue'import './styles/main.css'import App from './app.vue'
new Vue({
el:"#app",
template:'<App/>',
components:{App}
})
新建一个app.vue文件
<template>
<div id="app">
<img src="./images/logo.png" alt="logo" />
<span>{{msg}}</span>
<p class="test">test text</p>
</div></template><script>import Vue from 'vue'
export default {
name:'app',
data(){
return {
msg:"hello vue !!"
}
},
}
</script><style >
.test{
color:#020202
}
</style><style lang="less"><!--我好像还没说引入less哦,下面说-->
#app{
img{width:100px;}
}
</style>
别忘了弄张图片,写个main.css哦
/*main.css*/
@import './reset.css';
#app{
color:red;
}
用less或者sass
你可以在项目中用less或者sass,相对的就要安装less-loader和sass-loader
npm install --save-dev less-loader
npm install --save-dev sass-loader
如果没有在全局安装less或sass编译器的话还有安装一下,执行上面loader安装之前先安装less或sass
安装到本项目中
npm install --save-dev less
安装到全局中
npm install --g less
以less-loader为例,修改webpack.config.js
{
test:/\.less$/,
use:[
'vue-style-loader'
'css-loader',
'less-loader'
]
},
{
test:/\.vue$/,
loader:'vue-loader',
options:{
loaders:{
'less':[//lang属性对应的名称
'vue-style-loader'//首先给vue的样式loader过滤一遍
'css-loader',//css-loader,把css转js
'less-loader'//用less编译
]
}
}
}
使用vue单文件组件的时候给lang属性添加标识就可以了,less后缀的文件也会一起进行编译
<style lang="less">
#app{
img{width:100px;}
}
</style>
sass类似,但sass带有两种语法规范sass和scss,需要分别设置,下面就贴一点vue-cli的代码,不过多的介绍了。
打包运行一下
打包之前可以改改npm scripts,这样就可以看到打包进度,和隐藏不必要的信息
"build": "webpack --progress --hide-modules"
运行打包
npm run build
前端的环境
-
开发环境
-
生产环境
-
测试环境
-
预发布环境
-
上线环境
- 开发环境 和 生产环境 都是有前端静态服务器来提供 - 测试环境 本地客户端服务器提供 - 预发布和上线环境是 nginx
区分开发与生产环境
很多插件功能是在开发环境(development)用到的但是在s生产环境(production)用不到的,反之亦然。比如
-development用到的
- 热插拔调试
- 生成html模板
-production
- 用到的生成html模板
- css样式提取
- 公共模块提取
- JavaScript压缩
- …
第二种方法涉及到二次封装,就像官方vue-cli构建的项目一样,分成了三个配置文件,对目前的我们来说比较复杂,我们使用第一种方法,设置环境变量来区分部署环境。参考vue-cli生成的简单版工程(webpack-simple),我们发现npm script写得有点奇怪
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
在运行webpack命令之前运行了 cross-env NODE_ENV=develpoment和production,这就是给环境变量赋值的过程,但是单单这样写是无法执行的,我们需要安装一个插件——cross-env
npm install --save cross-env
这样我们就可以在之后运行在node环境的js 文件中访问到这些环境变量,通过process.env对象还能拿到package.json里面的配置信息,这就涉及到node的知识了,不多说。
const env = process.env.NODE_ENV
//获取工程的版本号const version = process.env.npm_package_version
简单点写,把环境变量的判断直接放到webpack.config.js文件的最下面
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry:{
app:'./src/main.js'
},
//...
}
/**
* 生成生产代码的时候才触发
*/if (process.env.NODE_ENV === 'production') {
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
])
}
生成html模板
之前根目录下index.html要我们自己引入js资源地址,有新的资源都要手动引入,很麻烦,这时候就会用到HtmlWebpackPlugin 插件,按照index.html作为模板在dist目录下生成带上所有资源的html 文件。
npm install --save-dev html-webpack-plugin
先通过require引入插件,然后在输出对象里面添加plugins属性,数据值类型是数组,数组成员new 插件添加插件就行。每个插件都有自己的配置项和规范,可以查 npmjs或者 他们的官方文档
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
entry:{
app:'./src/main.js'
},
output:{
path:path.resolve(__dirname,'./dist'),
filename:"js/[name].js",
},
module:{
rules:[
//...
]
},
plugins:[
new HtmlWebpackPlugin({
filename:'index.html',
title:'vue demo',
template:'./index.html',
})
],
externals:{
'jquery':'window.jQuery'
}
}
说明
- filename 生成的html的文件名,不填就默认是原文件名
- title title标签的内容
- template html模板地址,这里我们用我上一期建在跟目录的index.html
index.html的内容要改一改了,因为webpack打包完之后自动添加资源地址到html文件里,所以我们要删掉原本写上去的script标签
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<title>vue demo</title></head><body>
<div id="app">
</div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script></body></html>
有人可能会奇怪,这里为什么加了一个cdn的jQuery,因为我要在这里带过一个知识点:有时候我们会有用到cdn加速的库资源,但是不知道怎么在工程中使用。很简单我们在html模板中直接引入,然后在webpack.config.js配置中加一项“外部引入”(externals)
// webpack.config.js
externals:{
'jquery':'window.jQuery'
}
//app.vue中引入import $ from 'jquery'
热替换
使用热替换之前当然要先有一个web服务器环境啦,安装webpack-dev-server
npm install --save-dev webpack-dev-server
webpack-dev-server其实是一个独立的插件,但是webpack内置了它的配置项,属性devServer对应的就是它的配置项。
module.exports = {
entry:{
app:'./src/main.js'
},
output:{
path:path.resolve(__dirname,'./dist'),
filename:"js/[name].js",
},
devServer:{
contentBase:"./dist"
}
}
端口地址什么的都默认 http://localhost:8080/ ,就设置了跟资源目录地址contentBase。
热替换插件
热替换就是开发的过程中修改文件内容之后不用频繁刷新页面,修改会自动同步到浏览器中,webpack内部已经有这份插件了,不用安装直接都用就可以。在plugins添加一项 new webpack.HotModuleReplacementPlugin()就ok了
plugins:[
new HtmlWebpackPlugin({
filename:'index.html',
title:'vue demo',
template:'./index.html',
}),
new webpack.HotModuleReplacementPlugin()
]
改一下npm scripts
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
运行 npm run dev
,热部署搞定
webpack.config.js配置
单页面
- 入口文件
entry: 相对路径
- 出口文件
- 配置hash
output: {
path: path.resolve(__dirname,'dist'),
filename: 'js/app_[hash:6].js'
}
- 转换器: 将某一类型的文件转成另一个类型文件的一个工具,我们常用loader来表示
- 举例: css文件
- 所有的loader用一个module的配置项表示
module: {
rules: [
{} //每一个对象表示一个类型文件的转换器
]
}
多页面
const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const ExtractRootCss = new ExtractTextPlugin({filename:'styles/root.css',allChunks:false});
const ExtractVueCss = new ExtractTextPlugin({filename:'styles/[name]/style.css',allChunks:true});
module.exports = {
//other options...
module:{
rules:[
//...
{
test:/\.css$/,
//这里用的ExtractRootCss
use:ExtractRootCss.extract({
fallback:'style-loader',
use:['css-loader']
})
},
{
test:/\.less$/,
//这里用的ExtractRootCss
use:ExtractRootCss.extract({
fallback:'style-loader',
use:[
'css-loader',
'less-loader'
]
})
},
{
test:/\.vue$/,
loader:'vue-loader',
options:{
loaders:{
//这里用的ExtractVueCss
'css': ExtractVueCss.extract({
use: 'css-loader',
fallback: 'vue-style-loader' // <- 这是vue-loader的依赖,所以如果使用npm3,则不需要显式安装
}),
//这里用的ExtractVueCss
'less':
ExtractVueCss.extract({
use:[
'css-loader',
'less-loader'
],
fallback:'vue-style-loader'
})
},
}
},
]
},
plugins:[
new HtmlWebpackPlugin({
filename:'index.html',
title:'vue demo',
template:'./index.html',
}),
ExtractRootCss,//填入插件实例,复用的css
ExtractVueCss,//记得按顺序填入,vue内的css
new webpack.HotModuleReplacementPlugin(),
]
}