'use strict'
const utils = require('./utils')// 工具类
const webpack = require('webpack')
// 获取配置文件中默认的配置
const config = require('../config')
const merge = require('webpack-merge')// 使用webpack配置合并插件
const path = require('path')// node自带文件路径工具
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')// 这个插件自动生成HTML,并注入到.html文件中
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
// webpack.dev.conf.js与webpack.base.conf.js中的配置合并
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.dev.cssSourceMap,
usePostCSS: true
})
},
// 廉价模块-eval-源代码映射的开发速度更快
devtool: config.dev.devtool,
// 这些devServer选项应该在/config/index.js中进行定制。
devServer: {
clientLogLevel: "warning",
historyApiFallback: {
rewrites: [
{
from: /.*/,
to: path.posix.join(config.dev.assetsPublicPath, "index.html")
}
]
},
plugins: [
// 你可以理解为,通过配置了DefinePlugin,那么这里面的标识就相当于全局变量,你的业务代码可以直接使用配置的标识
new webpack.DefinePlugin({
"process.env": require("../config/dev.env")
}),
// hotModule插件让页面变动时,只重绘对应的模块,不会重绘整个HTML文件
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR在更新中显示正确的文件名。
// 在编译出现错误时,使用 NoEmitOnErrorsPlugin 来跳过输出阶段。这样可以确保输出资源不会包含错误
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
// 将生成的HTML代码注入index.html文件
new HtmlWebpackPlugin({
filename: "index.html",
template: "index.html",
inject: true
}),
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;
// friendly-errors-webpack-plugin用于更友好地输出webpack的警告、错误等信息
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);
}
})
})
在webpack.dev.conf.js中有引到webpack.base.conf.js下面来看看:
/*
* @Author: carrie
* @Date: 2018-05-02 16:41:24
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2018-05-03 09:45:19
*/
'use strict'
const path = require('path')// node自带的文件路径插件
const utils = require('./utils')// 工具类
const config = require('../config')
// vue-loader.conf配置文件是用来解决各种css文件的,定义了诸如css,less,sass之类的和样式有关的loader
const vueLoaderConfig = require('./vue-loader.conf')
// 在开头引入webpack,后面的plugins那里需要
var webpack = require('webpack')
// 此函数是用来返回当前目录的平行目录的路径,
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, "../"),
entry: {
//入口
app: "./src/main.js"
},
output: {
// 路径是config目录下的index.js中的build配置中的assetsRoot,也就是dist目录
path: config.build.assetsRoot,
filename: "[name].js",
// 上线地址,也就是真正的文件引用路径,如果是production生产环境,其实这里都是 '/'
publicPath:
process.env.NODE_ENV === "production"
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
// resolve是webpack的内置选项,顾名思义,决定要做的事情,也就是说当使用 import "jquery",该如何去执行这件事情,就是resolve配置项要做的,import jQuery from "./additional/dist/js/jquery" 这样会很麻烦,可以起个别名简化操作
resolve: {
// 省略扩展名,比方说import index form '../js/index', 会默认去找index文件,然后找index.js,.vue,.josn.
extensions: [".js", ".vue", ".json"],
alias: {
vue$: "vue/dist/vue.esm.js",
// 使用上面的resolve函数,意思是用@代替src的绝对路径
"@": resolve("src")
}
},
// 不同的模块使用不同的loader
module: {
rules: [
{
// 对vue文件,使用vue-loader解析
test: /\.vue$/,
loader: "vue-loader",
options: vueLoaderConfig
},
{
// babel-loader把es6解析成es5
test: /\.js$/,
loader: "babel-loader",
include: [
resolve("src"),
resolve("test"),
resolve("node_modules/webpack-dev-server/client")
]
},
{
// url-loader将文件大小低于下面option中limit的图片,转化为一个64位的DataURL,这样会省去很多请求,大于limit的,按[name].[hash:7].[ext]的命名方式放到了static/img下面,方便做cache
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]")
}
}
// 自定义Author:周云芳
// end 自定义Author:周云芳
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin("common.js"),
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery"
})
]
};