1.媒介
这几天,都遇到过有人问过类似的题目,就是用vue和webpack搭建目次的时刻,怎样把单页面运用的设置改成多文件运用,或许是怎样把多文件运用的设置改成单文件运用。这个状况,我之前有处置惩罚过,公司的同事教过我,我就针对这个状况写下此篇文章。列位假如以为我那边写得不够好,写错了,迎接指出,人人一同提高。
2.申明
起首,我用的vue和webpack的版本都是2.x的,请人人注意本身运用的版本,特别是webpack的版本,1和2照样有些区分的。
然后,项目搭建的流程我不多说了,之前写过文章,网上也有许多好文章值得进修。接下来我只针对webpack.config.js这个设置文件申明,因为我做项目的时刻,修改的基础就是这里,项目的文件虽然也有写法上的修改,然则谁人修改置信不会难到人人,假如真的不知怎样动手,我今后可能会再写文章。
3.单文件运用的设置
因为如今单文件运用写得比较多,一开始我就先放单文件运用的设置文件吧,代码以下
let path = require('path');
let webpack = require('webpack');
/*
html-webpack-plugin插件,webpack中天生HTML的插件,
细致能够去这里检察https://www.npmjs.com/package/html-webpack-plugin
*/
let HtmlWebpackPlugin = require('html-webpack-plugin');
/*
一个依据形式婚配猎取文件列表的node模块。
有关glob的细致用法能够在这里看到——https://github.com/isaacs/node-glob
*/
let glob = require('glob');
/*
webpack插件
*/
let CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
let UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
let publicPath = '/dist/';
//IP地点
let serverHost = getIPAdress();
let config = {
//进口文件
entry: {
index: path.resolve(__dirname, 'src/js/page/index.js'),
vendors: ['vue', 'vue-router','vue-resource','vuex','element-ui','element-ui/lib/theme-default/index.css'] // 须要举行零丁打包的文件
},
//出口文件
output: {
path: path.join(__dirname, 'dist'), //输出目次的设置,模板、款式、剧本、图片等资本的途径设置都相对于它
publicPath: publicPath, //模板、款式、剧本、图片等资本对应的server上的途径
filename: 'js/[name].js', //每一个页面对应的主js的天生设置
// chunkFilename: 'js/[name].asyncChunk.js?[chunkhash]' //chunk天生的设置
chunkFilename: 'js/[name].asyncChunk.js?'+new Date().getTime() //chunk天生的设置
},
module: {
//加载器
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader', // <style lang="scss">
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' // <style lang="sass">
}
}
},
{
test: /\.html$/,
loader: "raw-loader"
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["es2015","stage-0"],
plugins: ['syntax-dynamic-import']
}
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader'
},
{
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
loader: 'file-loader'
},
{
//图片加载器,相同file-loader,更适合图片,能够将较小的图片转成base64,削减http要求
//以下设置,将小于8192byte的图片转成base64码
test: /\.(png|jpg|gif)$/,
loader: 'url-loader?limit=8192&name=images/[hash].[ext]'
}
]
},
//插件
plugins: [
//天生HTML文件
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, 'dist/html/index.html'), //天生的html寄存途径,相对于path
template: path.resolve(__dirname, 'src/html/index.html'), //ejs模板途径,前面最好加上loader用于处置惩罚
inject: 'body', //js插进去的位置,true/'head'/'body'/false
chunks: ['load', 'vendors', 'vendor1', 'vendor2', 'index'],
hash: true
}),
//提取大众模块
new CommonsChunkPlugin({
name: 'vendors', // 将大众模块提取,天生名为`vendors`的chunk
//name: ['vendors', 'vendor1', 'vendor2', 'load'], // 将大众模块提取,天生名为`vendors`的chunk
minChunks: 2, //大众模块被运用的最小次数。设置为2,也就是同一个模块只要被2个之外的页面同时引用时才会被提取出来作为common chunks
// children:true //假如为true,那末大众组件的一切子依靠都将被挑选进来
}),
//在async chunk 内里找到复用 >= 2次的模块再零丁提取出来
new CommonsChunkPlugin({
async: 'lazy',
minChunks: (module, count) => ( //count 模块被复用的次数
count >= 2
)
}),
new UglifyJsPlugin({ //紧缩代码
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
},
except: ['$super', '$', 'exports', 'require', 'define', 'module'] //消除关键字
})
],
//运用webpack-dev-server
devServer: {
contentBase: path.join(__dirname, "/"),
host: serverHost,
port: 9090, //默许9090
inline: true, //能够监控js变化
hot: true//热启动
},
resolve: {
alias: {
vue: 'vue/dist/vue.js'
},
extensions:['.js','.scss','.vue','.json']// 能够不加后缀, 直接运用 import xx from 'xx' 的语法
}
};
module.exports = config;
/**
* @description 猎取当地IP地点
* @returns {string|*}
*/
function getIPAdress() {
let interfaces = require('os').networkInterfaces();
for (let devName in interfaces) {
let iface = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
}
4.多文件运用的设置
多文件如今用的不算许多,重要有时刻会担任公司一些运动的小项目会用到,代码以下。
let path = require('path');
let webpack = require('webpack');
/*
html-webpack-plugin插件,webpack中天生HTML的插件,
细致能够去这里检察https://www.npmjs.com/package/html-webpack-plugin
*/
let HtmlWebpackPlugin = require('html-webpack-plugin');
/*
一个依据形式婚配猎取文件列表的node模块。
有关glob的细致用法能够在这里看到——https://github.com/isaacs/node-glob
*/
let glob = require('glob');
/*
webpack插件
*/
let CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
let UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
let publicPath = '/dist/';
//经由过程getEntry函数猎取一切js剧本
let jsEntries = getEntry('./src/js/page/*.js');
//IP地点
let IPAddress = getIPAdress();
let serverHost = IPAddress;
let config = {
//进口文件
entry: jsEntries,
// entry: {
// index:jsEntries,
// vendors: ['vue', 'vue-router','vue-resource'] // 须要举行零丁打包的文件
// },
//出口文件
output: {
path: path.join(__dirname, 'dist'), //输出目次的设置,模板、款式、剧本、图片等资本的途径设置都相对于它
publicPath: publicPath, //模板、款式、剧本、图片等资本对应的server上的途径
filename: 'js/[name].js', //每一个页面对应的主js的天生设置
chunkFilename: 'js/[id].chunk.js?[chunkhash]' //chunk天生的设置
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader', // <style lang="scss">
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' // <style lang="sass">
}
}
},
{
test: /\.html$/,
loader: "raw-loader"
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["es2015","stage-0"],
plugins: ['syntax-dynamic-import']
}
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader'
},
{
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
loader: 'file-loader'
},
{
//图片加载器,相同file-loader,更适合图片,能够将较小的图片转成base64,削减http要求
//以下设置,将小于8192byte的图片转成base64码
test: /\.(png|jpg|gif)$/,
loader: 'url-loader?limit=8192&name=images/[hash].[ext]'
}
]
},
plugins: [
new CommonsChunkPlugin({
name: 'vendors', // 将大众模块提取,天生名为`vendors`的chunk
//name: ['vendors', 'vendor1', 'vendor2', 'load'], // 将大众模块提取,天生名为`vendors`的chunk
minChunks: 2, //大众模块被运用的最小次数。设置为2,也就是同一个模块只要被2个之外的页面同时引用时才会被提取出来作为common chunks
// children:true //假如为true,那末大众组件的一切子依靠都将被挑选进来
})
new UglifyJsPlugin({ //紧缩代码
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
},
except: ['$super', '$', 'exports', 'require', 'define', 'module'] //消除关键字
})
],
//运用webpack-dev-server
devServer: {
contentBase: path.join(__dirname, "/"),
host: serverHost,
port: 9090, //默许9090
inline: true, //能够监控js变化
hot: true//热启动
},
resolve: {
alias: {
vue: 'vue/dist/vue.js'
},
extensions:['.js','.scss','.vue','.json']// 能够不加后缀, 直接运用 import xx from 'xx' 的语法
}
};
//猎取目次下的一切.html文件的称号
let tplPages = Object.keys(getEntry('./src/html/*.html'));
tplPages.forEach((pathname)=> {
let conf = {
filename: path.resolve(__dirname, 'dist/html/'+ pathname +'.html'), //天生的html寄存途径,相对于path
template: path.resolve(__dirname, 'src/html/'+ pathname +'.html'), //ejs模板途径,前面最好加上loader用于处置惩罚
inject: 'body', //js插进去的位置,true/'head'/'body'/false
chunks: ['load', 'vendors', 'vendor1', 'vendor2', 'index'],
hash: true
};
//假如文件名和进口文件名所对应的js有婚配(如:index.html和index.js就是相婚配的,就往index.html内里插进去index.js;share.html和share.js就是相婚配的,就往share.html内里插进去share.js)
if (pathname in config.entry) {
conf.inject = 'body';
conf.chunks = ['vendors', pathname];
conf.hash = true;
}
//天生设置压栈
config.plugins.push(new HtmlWebpackPlugin(conf));
});
module.exports = config;
/**
* @description 猎取当地IP地点
* @returns {string|*}
*/
function getIPAdress() {
let interfaces = require('os').networkInterfaces();
for (let devName in interfaces) {
let iface = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
}
function getEntry(globPath) {
//猎取globPath途径下的一切文件
let files = glob.sync(globPath);
let entries = {},
entry, dirname, basename, pathname, extname;
//轮回
for (let i = 0; i < files.length; i++) {
entry = files[i];
dirname = path.dirname(entry);//返回途径的地点的文件夹称号
extname = path.extname(entry);//返回指定文件名的扩大称号
/**
* path.basename(p, [ext])
* 返回指定的文件名,返回效果可消除[ext]后缀字符串
* path.basename('/foo/bar/baz/asdf/quux.html', '.html')=>quux
*/
basename = path.basename(entry, extname);
pathname = path.join(dirname, basename);//途径兼并
entries[basename] = entry;
}
//返回map=>{fileName:fileUrl}
return entries;
}
5.区分总结
一对照,区分就是出来了,然则写法是迥然不同的。有区分是重如果下面几点
1.进口文件的区分,单页面运用进口文件是就是一个index.js('src/js/page/index.js'
)。而多页面运用的进口文件是一切须要用到的页面let jsEntries = getEntry('./src/js/page/*.js');
。(getEntry要领是返回一个目次下一切的.js文件的称号和途径,jsEntries就是一个对象数组,内里包含着./src/js/page
目次下一切的.js文件的称号和途径)
2.在多文件运用的设置中,HtmlWebpackPlugin这个插件是提取出来,在遍历getEntry('./src/html/*.html')
的过程当中,实行一次就往设置(config.plugins)那边push一次(config.plugins.push(new HtmlWebpackPlugin(conf))
)。为何如许写,人人应当很清晰了,有多少个进口文件,就得写多少次这个插件,new HtmlWebpackPlugin
多少次,假如进口文件只要一两个,两三个还好,假如有100个进口文件,岂不是要在config.plugins
那边写100次new HtmlWebpackPlugin
,所以就题目笔墨遍历了,轻易点。
结语
好了。单文件运用和多文件运用上,webpack.config.js是迥然不同的,区分就讨论到这里了。假如文章以为那边写得不好或许写错了,迎接指出。同时也愿望,这篇文章能帮到人人!