详解基于Vue2.0项目的webpack配置文件

Vue提供了一个很好的命令行工具:vue-cli,用来快速构建Vue项目。
现在,我们改造一个由vue-cli创建的simple project,使其提供更强大的功能。

1. 创建一个简单的Vue项目

vue init webpack-simple my-webpack-simple-demo

2. package.json

{
  ...
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --env=integrate",
    "build-test": "cross-env NODE_ENV=production webpack --progress --hide-modules --env=test",
    "build-release": "cross-env NODE_ENV=production webpack --progress --hide-modules --env=release"
  },
  "dependencies": {
    "vue": "^2.2.1"
  },
  "devDependencies": {
    "babel-core": "^6.0.0",
    "babel-loader": "^6.0.0",
    "babel-preset-latest": "^6.0.0",
    "clean-webpack-plugin": "^0.1.15",
    "cross-env": "^3.0.0",
    "css-loader": "^0.25.0",
    "element-ui": "^1.2.3",
    "extract-text-webpack-plugin": "^2.0.0-beta.4",
    "file-loader": "^0.9.0",
    "html-webpack-plugin": "^2.28.0",
    "node-sass": "^4.5.0",
    "sass-loader": "^5.0.1",
    "style-loader": "^0.13.2",
    "url-loader": "^0.5.8",
    "vue-cookie": "^1.1.3",
    "vue-loader": "^11.0.0",
    "vue-resource": "^1.2.1",
    "vue-router": "^2.3.0",
    "vue-style-loader": "^2.0.3",
    "vue-template-compiler": "^2.2.1",
    "vuex": "^2.2.1",
    "webpack": "^2.2.0",
    "webpack-dev-server": "^2.2.0"
  }
}

3. 文件结构

webpack.png

4. .babelrc

Babel是ES6转码器,可以将项目中用到的ES6语法编译为ES5语法。

我们需要安装babel-loader babel-core,然后新增.babelrc文件:

{
  "presets": [
    ["latest", {
      "es2015": { "modules": false }
    }]
  ]
}

5.webpack.config.js

详解请看注释:

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');

var srcPath = path.join(__dirname, './src/');

/*-----------------根据process变量找到对应的webconfig文件-----------------*/
function getEnv() {
    var argv = process.argv.slice(2);
    for (var i = 0; i < argv.length; i++) {
        if (argv[i].indexOf('--env=') >= 0) {
            return argv[i].substr(6);
        }
    }
}
//webconfig是api配置文件。一般来说,不同的环境后台api地址会不同
//例如:test环境下,api为http://test.api.com; 
//release环境下,api为http://release.api.com; 
//需要根据不同的环境,把api配置给相应的ajax插件,如vue-resource, axios
//例如,配置vue-resource: Vue.http.options.root = webconfig.host;
var env = getEnv();
var configPath = '';
switch (env) {
    case 'test' :
        configPath = path.join(__dirname, './src/config/webconfig_test.js');
        break;
    default :
        configPath = path.join(__dirname, './src/config/webconfig_release.js');
}
/*-----------------webpack 配置-----------------*/
module.exports = {
    //完整写法为entry:{main:  './src/main.js'},所以,[name]默认为"main"
    //也可以按照喜好自行定义[name]的名字
    entry: './src/main.js',
    output: {
        //必须是绝对路径(所以这里用到的是path.resolve,而不是path.join)
        //指定文件打包的输入目录
        path: path.resolve(__dirname, './dist'),
        //output.path中的URL以HTML页面为基准,表示资源的发布地址
        //当配置过该属性后,打包文件中所有通过相对路径引用的资源都会被配置的路径所替换
        // webpack-dev-server也会默认从publicPath为基准,使用它来决定在哪个目录下启用服务,来访问webpack输出的文件。
        publicPath: '/',
        // 指定输出文件的名称,[hash]会自动给文件名加上hash后缀
        filename: 'js/build-[hash].js',
        //异步加载的JS文件不会被打包到output->path下,所以需要为其做专门配置
        //[id]会自动为异步文件添加序列号
        //这里,和vue-router配合,实现切换路由时按需加载JS文件
        chunkFilename: 'js/[id].build.js?[chunkhash]'
    },
    //注意:利用ExtractTextPlugin插件将css或者scss(require("style.css"))单独打包到一个CSS文件
    //这样,样式不会内联到JS里面
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
                        // the "scss" and "sass" values for the lang attribute to the right configs here.
                        // other preprocessors should work out of the box, no loader config like this necessary.
                        'scss': 'vue-style-loader!css-loader!sass-loader',
                        'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
                    }
                    // other vue-loader options go here
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract({
                    fallbackLoader: 'style-loader',
                    loader: 'css-loader'
                })
            },
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    //resolve-url-loader may be chained before sass-loader if necessary
                    use: ['css-loader', 'sass-loader']
                })
            },
            {
                test: /\.(png|jpg|gif|svg|ico)$/,
                loader: 'file-loader',
                options: {
                    //图片导出路径
                    name: 'images/[name].[ext]'
                }
            }
        ]
    },
    resolve: {
        //模块别名定义,方便后续直接引用别名
        //例如,引用webconfig模块,语法为: require('webconfig')
        alias: {
            'vue$': 'vue/dist/vue.esm.js',
            appCss: srcPath + 'sass/app.scss',
            favicon: srcPath + 'images/favicon.ico',
            webconfig: configPath,
            apiconfig: srcPath + 'config/apiconfig.js'
        }
    },
    //webpack-dev-server配置
    devServer: {
        historyApiFallback: true,
        noInfo: true,
        //指定服务器文件路径
        contentBase: "./dist",
        port: 9002
    },
    performance: {
        //不展示警告或错误提示
        hints: false
    },
    //选择一种source map来增强调试过程,该选项会影响构建和重构建的速度
    devtool: '#eval-source-map',
    plugins: [
        //定义全局插件,不需要require()引入,直接可以使用模块名,如:webconfig.host;
        new webpack.ProvidePlugin({
            webconfig: 'webconfig',
            API_CONFIG_URL: "apiconfig",
        }),
        // 依据一个简单的模板,帮你生成最终的Html5文件
        // 这个文件中自动引用了你打包后的JS文件。
        // 每次编译都在文件名中插入一个不同的哈希值
        new HtmlWebpackPlugin({
            template: __dirname + "/index.tpl.html",
            favicon: 'src/images/favicon.ico',
        }),
        //将CSS从JS文件中分离出来,并添加到输出html文件中
        new ExtractTextPlugin('css/' + '[name]-[hash].css'),
        //每次build时,先清除dist包
        new CleanWebpackPlugin(['dist'], {
            verbose: true,
            dry: false
        })
    ]
};
//生成环境下的配置,提供文件压缩功能
if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map';
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            compress: {
                warnings: false
            }
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: true
        })
    ])
}

6. 用到的插件plugins

1). cross-env

cross-env用来设置环境变量。
Node环境中的环境变量为NODE_ENV,用process.env.NODE_ENV访问该变量。
可以看到package.json中的scripts用到这个功能:

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --env=integrate"
  }
2). webpack-dev-server

webpack-dev-server提供了一个服务器和实时重载(live reloading)功能。
webpack-dev-server是一个小型的node.js Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务。

3). html-webpack-plugin

该插件可以生成一个HTML5文件,它可以动态添加script标签加载webpack生成包。如果生成包带hash值,那么,就必须用这个插件了。

4). extract-text-webpack-plugin

将JavaScript中导入的CSS提取为单个CSS文件。

5). clean-webpack-plugin

删除目标目录下所有文件

更多高阶内容,可移步《小专栏-娜姐聊前端》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容