const path = require('path') const config = require('../config') const ExtractTextPlugin = require('extract-text-webpack-plugin') const packageConfig = require('../package.json') exports.assetsPath = function (_path) { const assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) } exports.cssLoaders = function (options) { options = options || {} //使用了css-loader和postcssLoader,通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法 const cssLoader = { loader: 'css-loader', options: { sourceMap: options.sourceMap } } const postcssLoader = { loader: 'postcss-loader', options: { sourceMap: options.sourceMap } } // generate loader string to be used with extract text plugin function generateLoaders (loader, loaderOptions) { const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] if (loader) { loaders.push({ loader: loader + '-loader', //Object.assign是es6语法的浅复制,后两者合并后复制完成赋值 options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // Extract CSS when that option is specified // (which is the case during production build) if (options.extract) { //ExtractTextPlugin可提取出文本,代表首先使用上面处理的loaders,当未能正确引入时使用vue-style-loader return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader', publicPath: '../../' }) } else { //返回vue-style-loader连接loaders的最终值 return ['vue-style-loader'].concat(loaders) } } // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(),//需要css-loader 和 vue-style-loader postcss: generateLoaders(),//需要css-loader和postcssLoader 和 vue-style-loader less: generateLoaders('less'), //需要less-loader 和 vue-style-loader sass: generateLoaders('sass', { indentedSyntax: true }), //需要sass-loader 和 vue-style-loader scss: generateLoaders('sass'), //需要sass-loader 和 vue-style-loader stylus: generateLoaders('stylus'), //需要stylus-loader 和 vue-style-loader styl: generateLoaders('stylus') //需要stylus-loader 和 vue-style-loader } } // Generate loaders for standalone style files (outside of .vue) exports.styleLoaders = function (options) { const output = [] const loaders = exports.cssLoaders(options) //将各种css,less,sass等综合在一起得出结果输出output for (const extension in loaders) { const loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) } return output } exports.createNotifierCallback = () => { //发送跨平台通知系统 const notifier = require('node-notifier') return (severity, errors) => { if (severity !== 'error') return //当报错时输出错误信息的标题,错误信息详情,副标题以及图标 const error = errors[0] const filename = error.file && error.file.split('!').pop() notifier.notify({ title: packageConfig.name, message: severity + ': ' + error.name, subtitle: filename || '', icon: path.join(__dirname, 'logo.png') }) } }
vue-loader.conf.js
该文件的主要作用就是处理.vue文件,解析这个文件中的每个语言块(template、script、style),转换成js可用的js模块。
const utils = require('./utils') const config = require('../config') const isProduction = process.env.NODE_ENV === 'production' const sourceMapEnabled = isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap //处理项目中的css文件,生产环境和测试环境默认是打开sourceMap,而extract中的提取样式到单独文件只有在生产环境中才需要 module.exports = { loaders: utils.cssLoaders({ sourceMap: sourceMapEnabled, extract: isProduction }), cssSourceMap: sourceMapEnabled, cacheBusting: config.dev.cacheBusting, // 在模版编译过程中,编译器可以将某些属性,如 src 路径,转换为require调用,以便目标资源可以由 webpack 处理 transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } }
webpack.base.conf.js
webpack.base.conf.js是开发和生产共同使用提出来的基础配置文件,主要实现配制入口,配置输出环境,配置模块resolve和插件等
const path = require('path') const utils = require('./utils') /** * [引入index.js文件路径] */ const config = require('../config') const vueLoaderConfig = require('./vue-loader.conf') /** * [获取文件路径] * @param dir [文件名称] *_dirname为当前模块文件所在目录的绝对路径* *@return 文件绝对路径 */ function resolve (dir) { return path.join(__dirname, '..', dir) } const createLintingRule = () => ({ test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter'), emitWarning: !config.dev.showEslintErrorsInOverlay } }) module.exports = { context: path.resolve(__dirname, '../'), /** * [入口文件配置] */ entry: { /** * [入口文件路径, babel-polyfill是对es6语法的支持] */ app: ['babel-polyfill', './src/main.js'], login: ['babel-polyfill', './src/loginMain.js'], license: ['babel-polyfill', './src/licenseMain.js'] }, /** * [文件导出配置] */ output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath //公共存放路径 }, resolve: { /** * [extensions: 配置文件的扩展名,当在important文件时,不用需要添加扩展名] */ extensions: ['.js', '.vue', '.json'], /** * [alias 给路径定义别名] */ alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') } }, /** *使用插件配置相应文件的处理方法 */ module: { rules: [ ...(config.dev.useEslint ? [createLintingRule()] : []), /** * [使用vue-loader将vue文件转化成js的模块] */ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, /** * [通过babel-loader将js进行编译成es5/es6 文件] */ { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, /** * [图片、音像、字体都使用url-loader进行处理,超过10000会编译成base64] */ { 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]') } }, /** * [canvas 解析] */ { test: path.resolve(`${resolve('src')}/lib/jtopo.js`), loader: ['exports-loader?window.JTopo', 'script-loader'] } ] }, //以下选项是Node.js全局变量或模块,这里主要是防止webpack注入一些Node.js的东西到vue中 node: { setImmediate: false, dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } }
webpack.dev.conf.js