版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zqh862735956/article/details/79610796
vue-cli+webpack配置分析
入口(package.json解析)
从package.json即最初始化的配置文件
该配置文件
//这里是指定了运行npm的缩写,npm run dev执行下面的文件,我理解是建立node环境
"script": {
//开发环境
"dev": "node build/dev-server.js",
//生产环境
"build": "cross-env BABEL_ENV=production NODE_ENV=production node build/build.js"
}
//这个里面放的都是依赖的模块
"dependencies": {
}
生成
pack.json文件时可以自己写的,也可以去生成,生成方法
//初始化
npm init//安装依赖模块
npm install
单个模块安装方法
这里一般都知道怎么安装,只是解释一下意思
$ npm install mint-ui --save
$ npm install mint-ui --save-dev
- 这里表示安装mint-ui模块,–save 会把依赖包名称添加到 package.json 文件 dependencies 键下
- –save-dev 则添加到 package.json 文件 devDependencies 键下
开发环境
开发环境的入口文件时
dev-server.js的配置
//配置文件
var config = require('../config')
//node环境无法判断当前是开发环境还是生产环境
//使用process.env.NODE_ENV作为当前的环境
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
//接口代理(关于vue的接口代理,我会单独总结一份出来)
var proxyMiddleware = require('http-proxy-middleware')
//指定开发环境
var webpackConfig = process.env.NODE_ENV === 'testing'
//生产环境配置文件
? require('./webpack.prod.conf')
//测试环境配置文件
: require('./webpack.dev.conf')
// 指定端口号
var port = process.env.PORT || config.dev.port
// 是否设置自动打开浏览器,不设置默认false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
//配置文件中http代理配置
var proxyTable = config.dev.proxyTable
// 启动 webpack 编译
var compiler = webpack(webpackConfig)
// 可以将编译后的文件暂存到内存中的插件
// https://github.com/webpack/webpack-dev-middleware
var devMiddleware = require('webpack-dev-middleware')(compiler, {
// 公共路径,与webpack的publicPath一样
publicPath: webpackConfig.output.publicPath,
// 不打印
quiet: true
})
// Hot-reload 热重载插件
// https://github.com/glenjamin/webpack-hot-middleware
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// 当tml-webpack-plugin template更改之后,强制刷新浏览器
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// 将 proxyTable 中的请求配置挂在到启动的 express 服务上
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
// 如果options的数据类型为string,则表示只设置了url,
// 所以需要将url设置为对象中的 target的值
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
//处理HTML5历史API的回退
// 如果不匹配就可以重定向到指定地址
app.use(require('connect-history-api-fallback')())
// 拼接 static 文件夹的静态资源路径
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// 静态文件服务
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
// 编译成功后打印网址信息
devMiddleware.waitUntilValid(function () {
console.log('> Listening at ' + uri + '\n')
})
//module.exports = app.listen(port, function (err) {
if (err) {
console.log(err)
return
}
// 如果配置了自动打开浏览器,且不是测试环境,则自动打开浏览器并跳到我们的开发地址
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
})
webpack配置
webpack.dev.conf.js开发环境配置
dev-server.js中使用了webpack.dev.conf.js文件,该文件是开发环境中webpack的配置入口。
// 工具函数集合 var utils = require('./utils') var webpack = require('webpack') // 配置文件 var config = require('../config') // webpack配置合并插件 var merge = require('webpack-merge') // webpack基础配置引入 var baseWebpackConfig = require('./webpack.base.conf') // 自动生产html 并且注入到 .html文件中的插件 var HtmlWebpackPlugin = require('html-webpack-plugin') // webpack 错误提示的插件 var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // 讲 Hot-reload 热重载的客户端代码添加到 webpack,.base.conf对应的入口entry一起打包 // vue热重载 即页面不刷新 更新组件 Object.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) }) module.exports = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, // cheap-module-eval-source-map is faster for development devtool: '#cheap-module-eval-source-map', plugins: [ new webpack.DefinePlugin({ 'process.env': config.dev.env }), // HotModule 插件在页面进行变更的时候只会重绘对应的页面模块,不会重绘整个 html 文件 new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), // 将 index.html 作为入口,注入 html 代码后生成 index.html文件 new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), new FriendlyErrorsPlugin() ] })
webpavk.base.conf.js(webpack基础配置,开发测试生产共用)
// node自带的文件路径工具
var path = require('path')
// 工具函数集合
var utils = require('./utils')
// 配置文件
var config = require('../config')
// 工具函数集合
var vueLoaderConfig = require('./vue-loader.conf')
/**
* 获得绝对路径
* @method resolve
* @param {String} dir 相对于本文件的路径
* @return {String} 绝对路径
*/
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
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'],
// 路径别名
alias: {
// 例如 import Vue from 'vue',会自动到 'vue/dist/vue.common.js'中寻找
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [{
// 审查 js 和 vue 文件
// https://github.com/MoOx/eslint-loader
test: /\.(js|vue)$/,
loader: 'eslint-loader',
// 表示预先处理
enforce: "pre",
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
// 处理 vue文件
// https://github.com/vuejs/vue-loader
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
// 编译 js
// https://github.com/babel/babel-loader
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
// 处理图片文件
// https://github.com/webpack-contrib/url-loader
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
// 处理字体文件
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
config/index.js
是主要的配置文件,包含静态文件的路径、是否开启sourceMap等。其中,分为两个部分dev(开发环境的配置)和build(生产环境的配置)。
// 详情见文档:https://vuejs-templates.github.io/webpack/env.html var path = require('path') module.exports = { // production 生产环境 build: { // 构建环境 env: require('./prod.env'), // 构建输出的index.html文件 index: path.resolve(__dirname, '../dist/index.html'), // 构建输出的静态资源路径 assetsRoot: path.resolve(__dirname, '../dist'), // 构建输出的二级目录 assetsSubDirectory: 'static', // 构建发布的根目录,可配置为资源服务器域名或 CDN 域名 assetsPublicPath: '/', // 是否开启 cssSourceMap productionSourceMap: true, // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin // 默认关闭 gzip,因为很多流行的静态资源主机,例如 Surge、Netlify,已经为所有静态资源开启gzip productionGzip: false, // 需要使用 gzip 压缩的文件扩展名 productionGzipExtensions: ['js', 'css'], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off // 运行“build”命令行时,加上一个参数,可以在构建完成后参看包分析报告 // true为开启,false为关闭 bundleAnalyzerReport: process.env.npm_config_report }, // dev 开发环境 dev: { // 构建环境 env: require('./dev.env'), // 端口号 port: 3333, // 是否自动打开浏览器 autoOpenBrowser: true, assetsSubDirectory: 'static', // 编译发布的根目录,可配置为资源服务器域名或 CDN 域名 assetsPublicPath: '/', // proxyTable 代理的接口(可跨域) // 使用方法:https://vuejs-templates.github.io/webpack/proxy.html proxyTable: {}, // CSS Sourcemaps off by default because relative paths are "buggy" // with this option, according to the CSS-Loader README // (https://github.com/webpack/css-loader#sourcemaps) // In our experience, they generally work as expected, // just be aware of this issue when enabling this option. // 默认情况下,关闭 CSS Sourcemaps,因为使用相对路径会报错。 // CSS-Loader README:https://github.com/webpack/css-loader#sourcemaps cssSourceMap: false } }
utils.js
utils.js也是一个被使用频率的文件,这个文件包含了三个工具函数:
- 生成静态资源的路径
- 生成 ExtractTextPlugin对象或loader字符串
生成 style-loader的配置
// node自带的文件路径工具 var path = require('path') // 配置文件 var config = require('../config') // 提取css的插件 // https://github.com/webpack-contrib/extract-text-webpack-plugin var ExtractTextPlugin = require('extract-text-webpack-plugin') /** * 生成静态资源的路径 * @method assertsPath * @param {String} _path 相对于静态资源文件夹的文件路径 * @return {String} 静态资源完整路径 */ exports.assetsPath = function (_path) { var assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory // path.posix.join与path.join一样,不过总是以 posix 兼容的方式交互 return path.posix.join(assetsSubDirectory, _path) } /** * 生成处理css的loaders配置 * @method cssLoaders * @param {Object} options 生成配置 * option = { * // 是否开启 sourceMap * sourceMap: true, * // 是否提取css * extract: true * } * @return {Object} 处理css的loaders配置对象 */ exports.cssLoaders = function (options) { options = options || {} var cssLoader = { loader: 'css-loader', options: { minimize: process.env.NODE_ENV === 'production', sourceMap: options.sourceMap } } /** * 生成 ExtractTextPlugin对象或loader字符串 * @method generateLoaders * @param {Array} loaders loader名称数组 * @return {String|Object} ExtractTextPlugin对象或loader字符串 */ function generateLoaders (loader, loaderOptions) { var loaders = [cssLoader] if (loader) { loaders.push({ // 例如,sass?indentedSyntax // 在?号前加上“-loader” loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // extract为true时,提取css // 生产环境中,默认为true if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } } // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html return { css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } } /** * 生成 style-loader的配置 * style-loader文档:https://github.com/webpack/style-loader * @method styleLoaders * @param {Object} options 生成配置 * option = { * // 是否开启 sourceMap * sourceMap: true, * // 是否提取css * extract: true * } * @return {Array} style-loader的配置 */ exports.styleLoaders = function (options) { var output = [] var loaders = exports.cssLoaders(options) for (var extension in loaders) { var loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) } return output
}
如有错误,欢迎指出