webpack4 构建vue多页工程
多页应用开发环境配置
构建开发环境的配置,需要使用到webpack-dev-server,以及webpack4中的mode配置和devServer。
而多页应用的开发则需要使用到html-webpack-plugin这个插件,来构建html
项目的目录结构
-- src
|-- views
|-- home
|-- index.js
|-- index.html
|-- index.vue
多页面的entry和页面的构建打包
const setMPA = () => {
const entrys = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, "src"));
Object.keys(entryFiles)
.map((index) => {
const entry = entryFiles[index];
const match = entry.match(/src\/views\/(.*)\/index\.js/);
const pageName = match && match[1];
entrys[pageName] = entry;
htmlWebpackPlugins(
new HtmlWebpackPlugin({
fileName: `${pageName}.html`,
template: path.join(__dirname, `src/views/${pageName}/index.html`),
title: `${pageName} title`
})
)
})
return {
entrys,
htmlWebpackPlugins
}
}
webpack.dev.js 开发环境的配置
// webpack.dev.js
const path = require('path');
const glob = require('glob');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const webpack = require('webpack');
const setMPA = () => {
const entrys = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, "src"));
Object.keys(entryFiles)
.map((index) => {
const entry = entryFiles[index];
const match = entry.match(/src\/views\/(.*)\/index\.js/);
const pageName = match && match[1];
entrys[pageName] = entry;
htmlWebpackPlugins(
new HtmlWebpackPlugin({
fileName: `${pageName}.html`,
template: path.join(__dirname, `src/views/${pageName}/index.html`),
title: `${pageName} title`
})
)
})
return {
entrys,
htmlWebpackPlugins
}
}
const { entrys, htmlWebpackPlugins } = setMPA();
module.exports = {
mode: 'development',
entry: entrys,
output: {
filename: 'static/js/[name].js',
path: path.posix.join(__dirname, 'dist')
},
resolve: {
alias: {
'@': path.join(__dirname, 'src')
}
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
},
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: 'images/[name].[ext]',
limit: 10240
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]'
}
}
]
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'vue-style-loader',
'css-loader',
'less-loader'
]
},
{
test: /\.styl(us)?$/,
use: [
'vue-style-loader',
'css-loader',
'stylue-loader'
]
}
]
},
plugins: [
new VueLoaderPlugin(),
// 热加载
new webpack.HotModuleReplacementPlugin()
].concat(htmlWebpackPlugins),
devServer: {
contentBase: path.join(__dirname, 'dist'),
hot: true
}
}
babelrc的配置,应用与编译ES的语法
/* .babelrc */
{
"presets": [
"@babel/perset-env"
]
}
浏览器的兼容版本,>1%==市场的使用份额大于1%
/* .browserslistrc */
last 2 version
>1%
IOS 7
正式环境配置
vue的正式环境需要配置mode: production,默认开启UglifyJsPlugin(js代码压缩)。
正式环境的资源hash迭代(hash、chunkhash、contenthash)
使用loader配置资源的提取,针对样式的提取使用mini-css-extract-plugin插件去提取,配合html-webpack-plguin把提取出来的css[chunk]配置进去html中
告警信息人性化,使用插件@soda/friendly-errors-webpack-plugin,
/**
* font and image 资源 --> hash
* 从js提取出font和image资源
*/
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]_[hash:8].[ext]',
limit: 10240 // 10k https://www.npmjs.com/package/url-loader#limit
}
}
]
},
{
test: /\.(woff|woff2|eof|ttf|tof)$/,
use: [
{
loader: 'file-loader', // https://www.npmjs.com/package/file-loader#name
options: {
name: '[name]_[hash:8].[ext]' // https://www.npmjs.com/package/file-loader#placeholders
}
}
]
}
]
}
}
sass 预处理器,配置时需要注意, css 样式处理,使用到contenthash
/**
* css --> contenthash 当css的内容没有任何改变,不会随着js[chunkhash]的改变而改变
* 遵从js的chunkhash
* 从js中提取出css到文件中
*/
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.(scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
fiber: require('fibers'),
implemation: require('sass'),
// indentedSyntax: true
}
}
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
{
test: /\.styl(us)?$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'stylus-loader'
]
}
]
},
plugins: [
// https://www.npmjs.com/package/mini-css-extract-plugin
// 提取出css
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
})
]
}
const path = requrie('path');
const HtmlWebpackPlguin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const FriendlyErrorsWebpackPlugin = require('@soda/friendly-errors-webpack-plugin');
const webpack = require('webpack');
const setMPA = () => {
const entrys = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, "src"));
Object.keys(entryFiles)
.map((index) => {
const entry = entryFiles[index];
const match = entry.match(/src\/views\/(.*)\/index\.js/);
const pageName = match && match[1];
entrys[pageName] = entry;
htmlWebpackPlugins(
new HtmlWebpackPlugin({
fileName: `${pageName}.html`,
template: path.join(__dirname, `src/views/${pageName}/index.html`),
title: `${pageName} title`
})
)
})
return {
entrys,
htmlWebpackPlugins
}
}
const { entrys, htmlWebpackPlguins } = setMPA();
module.exports = {
mode: 'production',
entry: entrys,
output: {
filename: '[name]_[chunkhash:8].js',
path: path.join(__dirname, 'dist')
},
resolve: {
// 配置文件夹的别名
alias: {
'@': path.join(__dirname, 'src')
}
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
},
{
test: /\.vue$/,
use: [
'cache-loader',
'vue-loader'
]
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]_[hash:8].[ext]',
limit: 10240 // 10k https://www.npmjs.com/package/url-loader#limit
}
}
]
},
{
test: /\.(woff|woff2|eof|ttf|tof)$/,
use: [
{
loader: 'file-loader', // https://www.npmjs.com/package/file-loader#name
options: {
name: '[name]_[hash:8].[ext]' // https://www.npmjs.com/package/file-loader#placeholders
}
}
]
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.(scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
fiber: require('fibers'),
implemation: require('sass'),
// indentedSyntax: true
}
}
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
{
test: /\.styl(us)?$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'stylus-loader'
]
}
]
},
plugins: [
new VueLoaderPlugin(), // vue-loader15版本之后,需要添加添加此插件
// 重新打包是清除打包的内容
new CleanWebpackPlugin(),
// 提取css
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
}),
// https://www.npmjs.com/package/@soda/friendly-errors-webpack-plugin
new FriendlyErrorsWebpackPlugin()
].concat(htmlWebpackPlugins)
}