webpack构建vue项目的详细教程(配置篇)
最近公司要求用vue重构项目,还涉及到模块化开发,于是乎,我专门花了几天的时间研究了一下webpack这个目前来看比较热门的模块加载兼打包工具,发现上手并不是很容易,现将总结的一些有关配置的心得分享出来,欢迎大神来拍砖。。。
一、新建一个项目目录,cd/d定位进去,然后输入npminit,会提示你填写一些项目的信息,一直回车默认就好了,或者直接执行npminit-y直接跳过,这样就在项目目录下生成了一个package.json文件。
二、接下来就是通过npm安装项目依赖项,命令行输入:npminstallbabel-loaderbabel-corebabel-plugin-transform-runtimebabel-preset-es2015babel-preset-stage-0babel-runtimevue-loadervue-html-loadervue-hot-reload-apicss-loaderstyle-loaderwebpackwebpack-dev-server--save-dev,继续输入npminstallvue@^1.0.26--save。
这里注意的几个点如下:
1.需要安装的依赖项视具体的项目需求来定,我只是安了几个必需的,后期会再加;
2.输入之后如果一直报错或者光标一直在转动,要么是npm版本太低(需要3+),要么将npm改成cnpm,如果没有安装淘宝NPM镜像,可以先输入npminstall-gcnpm--registry=https://registry.npm.taobao.org,接着输入cnpm-v查看是否安装完成,然后就可以使用cnpm来代替npm;
3.可以先修改package.json文件中的devDependencies和dependencies,然后再输入npminstall进行一次性安装(偷懒的做法,嘿嘿);
4.dependencies中的vue默认安装2+,如果dependencies中的vue选择^1.0.26,那么devDependencies中对应的vue-loader最好选择^7.3.0,vue-hot-reload-api最好选择^1.2.0,否则就会报错;
5.dependencies中的vue-router默认安装2+,无法识别router.map()这个方法,如果想要用回这个方法,最好选择^0.7.13;
6.有时安装一个依赖项,会提示还需要一并安装别的依赖项,例如:如果要安装bootstrap-loader,会提示要求安装node-sasssass-loaderresolve-url-loader;要安装less-loader,会提示要求安装less;
完成这一步之后,会在项目目录下生成一个名node_modules的文件,对应的package.json文件中的内容变动如下(我额外添加了几个依赖项):
"devDependencies":{
"autoprefixer-loader":"^3.2.0",
"babel-core":"^6.18.2",
"babel-loader":"^6.2.7",
"babel-plugin-transform-runtime":"^6.15.0",
"babel-preset-es2015":"^6.18.0",
"babel-preset-stage-0":"^6.16.0",
"babel-runtime":"^6.18.0",
"css-loader":"^0.25.0",
"debug":"^2.2.0",
"express":"^4.14.0",
"extract-text-webpack-plugin":"^1.0.1",
"file-loader":"^0.9.0",
"html-webpack-plugin":"^2.24.1",
"jquery":"^3.1.1",
"less":"^2.7.1",
"less-loader":"^2.2.3",
"style-loader":"^0.13.1",
"url-loader":"^0.5.7",
"vue-hot-reload-api":"^1.2.0",
"vue-html-loader":"^1.2.3",
"vue-loader":"^7.3.0",
"webpack":"^1.13.3",
"webpack-dev-middleware":"^1.8.4",
"webpack-dev-server":"^1.16.2",
"webpack-hot-middleware":"^2.13.1"
},
"dependencies":{
"vue":"^1.0.26",
"vue-router":"^0.7.13"
}
三、在项目目录下新建一个名为src的目录,里面用于存放入口文件(index.js)、项目源文件(html,css,js,img之类的)、组件(.vue后缀),我的src目录结构大致如下:
src -entry -index.js -pages -components -css -img -js -index.html -public
当然,有输入目录,就有输出目录,即在项目目录下新建一个output目录,用于放置生产出来的各种资源文件。
四、在项目目录下新建一个名为build目录,里面用于存放各种配置文件,涉及到基础配置、开发和生产环境、静态服务器以及热加载,详细的内容请看下面的代码:
1.webpack.config.js(基础配置文件)
//引入依赖模块
varpath=require('path');
varwebpack=require('webpack');
varExtractTextPlugin=require('extract-text-webpack-plugin');
module.exports={
//入口文件,路径相对于本文件所在的位置,可以写成字符串、数组、对象
entry:{
//path.resolve([from...],to)将to参数解析为绝对路径
index:path.resolve(__dirname,'../src/entry/index.js'),
//需要被提取为公共模块的群组
vendors:['vue','vue-router','jquery'],
},
//输出配置
output:{
//输出文件,路径相对于本文件所在的位置
path:path.resolve(__dirname,'../output/static/js/'),
//设置publicPath这个属性会出现很多问题:
//1.可以看成输出文件的另一种路径,差别路径是相对于生成的html文件;
//2.也可以看成网站运行时的访问路径;
//3.该属性的好处在于当你配置了图片CDN的地址,本地开发时引用本地的图片资源,上线打包时就将资源全部指向CDN了,如果没有确定的发布地址不建议配置该属性,特别是在打包图片时,路径很容易出现混乱,如果没有设置,则默认从站点根目录加载
//publicPath:'../static/js/',
//基于文件的md5生成Hash名称的script来防止缓存
filename:'[name].[hash].js',
//非主入口的文件名,即未被列在entry中,却又需要被打包出来的文件命名配置
chunkFilename:'[id].[chunkhash].js'
},
//其他解决方案
resolve:{
//require时省略的扩展名,遇到.vue结尾的也要去加载
extensions:['','.js','.vue'],
//模块别名地址,方便后续直接引用别名,无须写长长的地址,注意如果后续不能识别该别名,需要先设置root
alias:{}
},
//不进行打包的模块
externals:{},
//模块加载器
module:{
//loader相当于gulp里的task,用来处理在入口文件中require的和其他方式引用进来的文件,test是正则表达式,匹配要处理的文件;loader匹配要使用的loader,"-loader"可以省略;include把要处理的目录包括进来,exclude排除不处理的目录
loaders:[
//使用vue-loader加载.vue结尾的文件
{
test:/\.vue$/,
loader:'vue-loader',
exclude:/node_modules/
},
//使用babel加载.js结尾的文件
{
test:/\.js$/,
loader:'babel',
exclude:/node_modules/,
query:{
presets:['es2015','stage-0'],
plugins:['transform-runtime']
}
},
//使用css-loader和style-loader加载.css结尾的文件
{
test:/\.css$/,
//将样式抽取出来为独立的文件
loader:ExtractTextPlugin.extract("style-loader","css-loader!autoprefixer-loader"),
exclude:/node_modules/
},
//使用less-loader、css-loader和style-loade加载.less结尾的文件
{
test:/\.less$/,
//将样式抽取出来为独立的文件
loader:ExtractTextPlugin.extract("style-loader","css-loader!autoprefixer-loader!less-loader"),
exclude:/node_modules/
},
//加载图片
{
test:/\.(png|jpg|gif)$/,
loader:'url-loader',
query:{
//把较小的图片转换成base64的字符串内嵌在生成的js文件里
limit:10000,
//路径要与当前配置文件下的publicPath相结合
name:'../img/[name].[ext]?[hash:7]'
}
},
//加载图标
{
test:/\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
loader:'file-loader',
query:{
//把较小的图标转换成base64的字符串内嵌在生成的js文件里
limit:10000,
name:'../fonts/[name].[ext]?[hash:7]',
prefix:'font'
}
},
]
},
//配置插件项
plugins:[]
}
2.webpack.dev.config.js(开发环境下的配置文件)
//引入依赖模块
varpath=require('path');
varwebpack=require('webpack');
varHtmlWebpackPlugin=require('html-webpack-plugin');
varExtractTextPlugin=require('extract-text-webpack-plugin');
//引入基本配置
varconfig=require('./webpack.config.js');
//必须修改原配置中网站运行时的访问路径,相当于绝对路径,修改完之后,当前配置文件下的很多相对路径都是相对于这个来设定;
//注意:webpack-dev-server会实时的编译,但是最后的编译的文件并没有输出到目标文件夹,而是保存到了内存当中
config.output.publicPath='/';
//重新配置模块加载器
config.module={
//test是正则表达式,匹配要处理的文件;loader匹配要使用的loader,"-loader"可以省略;include把要处理的目录包括进来,exclude排除不处理的目录
loaders:[
//使用vue-loader加载.vue结尾的文件
{
test:/\.vue$/,
loader:'vue-loader',
exclude:/node_modules/
},
//使用babel加载.js结尾的文件
{
test:/\.js$/,
loader:'babel',
exclude:/node_modules/,
query:{
presets:['es2015','stage-0'],
plugins:['transform-runtime']
}
},
//使用css-loader、autoprefixer-loader和style-loader加载.css结尾的文件
{
test:/\.css$/,
//将样式抽取出来为独立的文件
loader:ExtractTextPlugin.extract("style-loader","css-loader!autoprefixer-loader"),
exclude:/node_modules/
},
//使用less-loader、autoprefixer-loader、css-loader和style-loade加载.less结尾的文件
{
test:/\.less$/,
//将样式抽取出来为独立的文件
loader:ExtractTextPlugin.extract("style-loader","css-loader!autoprefixer-loader!less-loader"),
exclude:/node_modules/
},
//加载图片
{
test:/\.(png|jpg|gif)$/,
loader:'url-loader',
query:{
//把较小的图片转换成base64的字符串内嵌在生成的js文件里
limit:10000,
//路径和生产环境下的不同,要与修改后的publickPath相结合
name:'img/[name].[ext]?[hash:7]'
}
},
//加载图标
{
test:/\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
loader:'file-loader',
query:{
limit:10000,
//路径和生产环境下的不同,要与修改后的publickPath相结合
name:'fonts/[name].[ext]?[hash:7]',
prefix:'font'
}
},
]
};
//重新配置插件项
config.plugins=[
//位于开发环境下
newwebpack.DefinePlugin({
'process.env':{
NODE_ENV:'"development"'
}
}),
//自动生成html插件,如果创建多个HtmlWebpackPlugin的实例,就会生成多个页面
newHtmlWebpackPlugin({
//生成html文件的名字,路径和生产环境下的不同,要与修改后的publickPath相结合,否则开启服务器后页面空白
filename:'src/pages/index.html',
//源文件,路径相对于本文件所在的位置
template:path.resolve(__dirname,'../src/pages/index.html'),
//需要引入entry里面的哪几个入口,如果entry里有公共模块,记住一定要引入
chunks:['vendors','index'],
//要把