Vue中webpack的初步解析
1. build目录和config目录,以及package.json
- webpack.base.conf.js,开发和生产环境共同的基本配置
- webpack.dev.conf.js, 开发打包配置
- webpack.prod.conf.js, 生产打包配置
- utils.js, 环境配置中所用到的一些方法
- index.js, 其中dev和build分别是打包配置项,分别用于webpack.dev.conf.js和webpack.prod.conf.js中
- dev.env.js, prod.env.js分别是生产、 开发环境中公用数据的配置,全局可访问,可配置axios.baseUrl
- index.js注释如下
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
//代理,处理跨域
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
//自动打开浏览器
autoOpenBrowser:false,
errorOverlay: true,
notifyOnErrors: true,
poll:false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// https://webpack.js.org/configuration/devtool/#development
//将解析后的代码映射到源码上,具体到行数,方便读取报错
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
//打包后项目的根路径
assetsRoot: path.resolve(__dirname, '../dist'),
//根目录下创建个子目录,static
assetsSubDirectory: 'static',
//在打包后生成的js,css引入的路径,前加上assetsPublicPath.这里是设置打包后js/css引入的公用路径,这个/表示从根目录开始,我们可以改为./ , 意为按当前相对路径引入
assetsPublicPath: '/',
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
}
}
- webpack.base.conf.js注释如下
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const webpack = require('webpack')
// 对于以/开始的路径片段,
// path.join只是简单的将该路径片段进行拼接,
// path.resolve将以/开始的路径片段作为根目录,在此之前的路径将会被丢弃,就像是在node中使用cd命令(cd /)一样。
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
//context 基础目录,用于从配置中解析入口起点(entry)和 loader
context: path.resolve(__dirname, '../'),
//入口文件
entry: {
app: './src/main.js'
},
//打包输出的文件,引用config/index/build中的配置
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
//配置模块如何解析
resolve: {
extensions: ['.js', '.vue', '.json'],
//配置一个别名,确保import或require引入时更方便
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
//插件,旨在解决loader无法解决的事
plugins:[
//这样的话,全局皆可引用,注意,开头必须引入webpack,即const webpack = require('webpack')
//ProvidePlugin 自动加载模块,而不必到处 import 或 require
new webpack.ProvidePlugin({
$:'jquery'
})
],
//模块解析
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader', //loader 和 use 等同
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test:/\.less$/,
loader:'style-loader!css-loader!less-loader'
}
]
},
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
- webpack.dev.conf.js注释如下
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
//自主设置域名与端口的方法,在npm run dev之前,在其npm中命令形式设置环境如下
//export HOST=vue.my
//export PORT=9090
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
//css 模块加载解析
rules: utils.styleLoaders({
sourceMap: config.dev.cssSourceMap,
usePostCSS: true
})
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{
from: /.*/,
to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
//watchOptions.poll通过传递 true 开启 poll,或者指定毫秒为单位进行轮询,监听文件修改,当文件改变时,重新构建
poll: config.dev.poll,
}
},
plugins: [
//DefinePlugin 允许创建一个在编译时可以配置的全局常量
//参考链接: https://webpack.docschina.org/plugins/define-plugin/#src/components/Sidebar/Sidebar.jsx
//这里使得config/dev.env.js内的数据为全局常量,任何地方都可以访问
new webpack.DefinePlugin({
//配置环境为生产环境
'process.env': require('../config/dev.env')
}),
//模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面
//参考链接: https://webpack.docschina.org/concepts/hot-module-replacement
new webpack.HotModuleReplacementPlugin(),
// HMR shows correct file names in console on update.
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
// every webpack,This will generate a file index.html,and import relative js、css.
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html', //生成的html,引用vue自带的模板index.html
inject: true
}),
// copy custom static assets
// 复制指定目录到指定根目录
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
//启动服务
module.exports = new Promise((resolve, reject) => {
//确定端口
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})