详细的配置可以参考官网:https://doc.webpack-china.org/guides/

一开始做项目时都是直接从组里前辈搭建好的脚手架开始写代码,到后来自己写新项目时又是拷贝之前的工程作为脚手架开始。对于脚手架本身却不甚了解,不仅不思考为什么更是没有改进的想法,怪不得工作满一年了却总觉得自己的技术水平在原地踏步,就是没有总结和思考。

目前组里的技术栈都是使用vue+koa,使用webpack的好处一是方便写vue的单文件组件,二是打包文件方便生产部署再加上能无所顾虑的应用语言的新特性。

1. 配置文件

官方文档推荐写webpack配置文件时,先写出一个基本配置文件(base)包含入口、输出等,再根据开发/生产环境所需要插件的不同,利用webpack-merge生成三个配置文件: dev、prod、analyze

package.json 依赖参考

"devDependencies": {
"babel-core": "^6.18.2",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.18.0",
"css-loader": "^0.28.4",
"koa-webpack-dev-middleware": "^1.4.0",
"koa-webpack-hot-middleware": "^1.0.3",
"less": "^2.7.1",
"less-loader": "^4.0.5",
"style-loader": "^0.18.2",
"url-loader": "^0.5.7",
"vue-loader": "^12.2.2",
"webpack": "^3.3.0",
"webpack-bundle-analyzer": "^2.8.3",
"webpack-dev-middleware": "^1.11.0",
"webpack-dev-server": "^2.6.1",
"webpack-hot-middleware": "^2.13.1",
"webpack-koa-hot-middleware": "^0.1.2",
"webpack-manifest-plugin": "^1.2.1",
"webpack-merge": "^4.1.0"
}

webpack.config.base.js

 'use strict'
let path = require('path');
let webpack = require('webpack');
let WebpackManifestPlugin = require("webpack-manifest-plugin"); module.exports = {
output: {
path: path.resolve(__dirname, '..', 'build')
},
resolve: {
extensions: ['.js', '.vue'],
modules: ['node_modules'],
alias: {
'leafletCSS': 'leaflet/dist/leaflet.css',
'leaflet$': 'leaflet/dist/leaflet.js',
'vue$': 'vue/dist/vue.min.js',
'vue-resource$': 'vue-resource/dist/vue-resource.min.js'
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|jpe?g|gif|svg|woff2?|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
},
plugins: [
new WebpackManifestPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.indexOf('node_modules') !== -1;
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
chunks: ['qq', 'navi', 'log', 'guide', 'apply', 'voice', 'pianhang', 'dynamic'], //这里输入需要提取公共代码的entry
minChunks: 2
}),
//CommonChunksPlugin will now extract all the common modules from vendor and main bundles
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest', //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
}),
]
}

第16行代码可以参考这里这里,默认NPM包导出的是运行时构建,Vue2的运行时构建不支持单文件组件的template

第58行的 WebpackManifestPlugin 作用是将输出文件名保存在文件中 (当输出文件名带 chunkhash 时很有用,参考这里)

第59~74行的 CommonsChunkPlugin 作用是从打包后的 bundle 文件中提取公共模块,将 npm install 的公共模块和业务代码分开,这样浏览器就可以一直缓存公共模块的bundle,参考这里。第一个 CommonsChunkPlugin 作用是将 node_modules 里的模块提取到 vendor.js 里;第二个 CommonsChunkPlugin 作用是将 entry 里的公共代码提取出来放在 common.js 里,参考这里;第三个 CommonsChunkPlugin 作用是将 webpack 运行时代码放在 manifest.js 里

webpack.config.dev.js

 "use strict"
let webpack = require('webpack');
let merge = require('webpack-merge');
let base_config = require('./webpack.config.base'); module.exports = merge(base_config, {
entry: {
qq: ['./src/qq/qq.js', 'webpack-hot-middleware/client'],
navi: ['./src/navi/navi.js', 'webpack-hot-middleware/client'],
log: ['./src/log/log.js', 'webpack-hot-middleware/client'],
guide: ['./src/guide/guide.js', 'webpack-hot-middleware/client'],
apply: ['./src/apply/apply.js', 'webpack-hot-middleware/client'],
voice: ['./src/voice/voice.js', 'webpack-hot-middleware/client'],
pianhang: ['./src/pianhang/pianhang.js', 'webpack-hot-middleware/client'],
dynamic: ['./src/dynamic/dynamic.js', 'webpack-hot-middleware/client']
},
output: {
filename: '[name].js',
},
devtool: '#eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
]
});

第 20 行设置source-map,方便用浏览器查看源代码

webpack.config.prod.js

 "use strict"
let webpack = require('webpack');
let merge = require('webpack-merge');
let base_config = require('./webpack.config.base'); module.exports = merge(base_config, {
entry: {
qq: ['./src/qq/qq.js'],
navi: ['./src/navi/navi.js'],
log: ['./src/log/log.js'],
guide: ['./src/guide/guide.js'],
apply: ['./src/apply/apply.js'],
voice: ['./src/voice/voice.js'],
pianhang: ['./src/pianhang/pianhang.js'],
dynamic: ['./src/dynamic/dynamic.js'],
},
output: {
filename: '[name].[chunkhash].js',
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
});

第 21 行 UglifyJsPlugin 的作用是压缩、混淆代码

webpack.config.analyze.js

 "use strict"

 let webpack = require('webpack');
let merge = require('webpack-merge');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
let prod_config = require('./webpack.config.prod'); module.exports = merge(prod_config, {
plugins: [
new BundleAnalyzerPlugin()
]
});

analyze 文件的作用利用 webpack-bundle-analyzer 插件分析打包情况,

webpack --config ./config/webpack.config.analyze.js

运行结果如下:

webpack的配置文件自定义程度很高,所以在参考他人配置时最好能弄清楚为什么要这样写

2. webpack-dev-server 

在开发过程中另一个重要的东西是 webpack-dev-server,它的作用是当你改动源代码后能自动重新打包,再加上 webpack 的HMR-模块热替换特性,这样改动代码就能直接在浏览器里看到效果,省却了代码手动打包+刷新浏览器的步骤。使用 webpack-dev-server 有 CLI 和 API 两种使用方法。

CLI 方式设置 dev 文件中的 HotModuleReplacementPlugin 和 devServer 启用 HMR。启动的命令为:

webpack-dev-server --config ./config/webpack.config.dev.js

API 方式直接在命令里设置参数,如:(这里用到了 Unix Domin Socket,也可以直接指定 ip和端口)

webpack-dev-server --config config/webpack.dev.config.js --public 0.0.0.0:8056 --progress --inline --hot --socket .dev-shared/sockets/webpack.sock

webpack-dev-server 的方式配置简单,缺点是引入 bundle 比较麻烦,需要指定其它端口

3. webpack-dev-middleware 

上述配置文件就是使用的该方法,需要有 koa-webpack-dev-middleware、koa-webpack-hot-middleware(热更新)。然后在 index.js 里写:

 if (process.env.NODE_ENV == 'dev') {
let webpack = require('webpack');
let webpackConfig = require('./config/webpack.config.dev.js');
let webpackDevMiddleware = require('koa-webpack-dev-middleware');
let webpackHotMiddleware = require('koa-webpack-hot-middleware');
let compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler));
app.use(webpackHotMiddleware(compiler));
}

这样就不需要通过额外的端口获取 bundle 文件了,注意这里是 koa 环境

4. 如何在前端框架里引入 bundle

由于 webpack prod 配置文件里使用了 chunkhash 作为 bundle 的名字的一部分,修改业务代码,chunkhash 会发生改变,所以需要通过一些方法自动将 bundle 名字注入到前端页面里:

第一种方法是通过在后端 controller 里读取 manifest.json 里的内容,然后通过模板引擎,注入到页面里,例如 nunjucks:

{% for path in paths %}
<script src="{{path}}"></script>
{% endfor %}

第二种方法是拓展模板引擎命令,例如 xtpl:

{{{ xScript('manifest.js') }}}
{{{ xScript('vendor.js') }}}
{{{ xScript('common.js') }}}
{{{ xScript('apply.js') }}}

xtpl 命令拓展示例 xtpl.ext.js :

 let xtplApp = require('xtpl/lib/koa');
let xtpl = require('xtpl/lib/xtpl');
let XTemplate = xtpl.XTemplate; XTemplate.addCommand('xScript', function(scope, option){
let name = option.params[0];
if (process.env.NODE_ENV !== 'dev') {
let assets_map = require('./manifest');
name = assets_map[name];
}
return '<script src="' + name + '" ></script>';
}); module.exports = xtplApp;

然后在 index.js 里

let xtpl = require('./extensions/xtpl.ext');

注意引入 bundle 的时候要注意引入顺序:manifest > vendor > common > entry,否则可能会报 ReferenceError: webpackJsonp is not defined 错误,还要注意要有 .babelrc 文件:

{
"presets": ["es2015"]
}

否则会报 SyntaxError: Unexpected token: name (xxxxxx) from Uglify plugin 之类的错误,无法识别语言新特性

webpack2配置的更多相关文章

  1. webpack2配置备份

    package.json: { "name": "leyi", "version": "1.0.0", "ma ...

  2. webpack2 配置 示例

    // https://github.com/webpack-contrib/extract-text-webpack-plugin var webpack = require("webpac ...

  3. webpack2的配置属性说明entry,output,state,plugins,node,module,context

    Webpack2配置属性详解 webpack说明 webpack是前端构建的一个核心所在,如果说后端构建就是把高级语言代码编译成机器码,那么前端的构建就是重新组合原有的代码,虽然并不编译成机器码,但实 ...

  4. eslint webpack2 vue-loader配置

    eslint是一个代码检测工具 官网如下http://eslint.cn/ npm install eslint --save-dev 需要这几个npm包: eslint eslint-loader ...

  5. 一步步构造自己的vue2.0+webpack环境

    前面vue2.0和webpack都已经有接触了些(vue.js入门,webpack入门之简单例子跑起来),现在开始学习如何构造自己的vue2.0+webpack环境. 1.首先新建一个目录vue-wk ...

  6. SpringBoot vue

    springboot 整合vue就行前后端完全分离,监听器,过滤器,拦截器 https://github.com/ninuxGithub/spring-boot-vue-separateA blog ...

  7. webpack2.0配置postcss-loader

    使用webpack2.0配置postcssloader 安装postcss-loader npm install --save-dev postcss-loader 然后配置webpack.confi ...

  8. Webpack 2 视频教程 011 - Webpack2 中加载 CSS 的相关配置与实战

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  9. 通过webpack2从0开始配置自己的vue项目 1

    PS 阅读者需要node基础.webpack原理知识.vue基础 安装node 这个网上很多教程 打开终端 创建项目 npm init 全局安装: cnpm i webpack webpack-dev ...

随机推荐

  1. SSDT表概念具体解释

    SSDT 的全称是 System Services Descriptor Table,系统服务描写叙述符表. 这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系 ...

  2. Android “swipe” vs “fling”

    onFling will get executed when a user makes a "fling" motion, and said motion has a veloci ...

  3. 采购订单打印并预览PDF

    *&---------------------------------------------------------------------* *& Report Z01MMF019 ...

  4. Oracle Shared Pool 原理

    Oracle Shared Pool 原理 由于shared pool中最重要的是library cache,所以本文主要讲解Library cache的结构,library cache latch, ...

  5. 微信小程序组件button

    表单组件button:官方文档 Demo Code: var types=['default', 'primary', 'warn']; var pageObject = { data: { defa ...

  6. Django 知识补漏单例模式

    Django 知识补漏单例模式 单例模式:(说白了就是)创建一个类的实例.在 Python 中,我们可以用多种方法来实现单例模式: 1.文件导入的形式(常用) s1.py class Foo(obje ...

  7. Saltstack sls文件:批量安装服务

    一.使用saltstack 批量安装nginx 1.创建salt目录 mkdir /srv/{salt,pillar} 2.再/srv/salt/下创建sls文件 vim nginx_install. ...

  8. 2018-2019-2 20165114《网络对抗技术》Exp3 免杀原理与实践

    Exp3 免杀原理与实践 目录 一.实验内容 二.基础问题回答 (1)杀软是如何检测出恶意代码的? (2)免杀是做什么? (3)免杀的基本方法有哪些? 三.实践过程记录 正确使用msf编码器,msfv ...

  9. Maven的SSM框架配置文件:

    applicationContext.xml: <?xml version="1.0" encoding="UTF-8"?> <beans x ...

  10. Block作为返回值时的使用

    昨天使用一个小例子简单说明了下Block作为参数时的使用. 今天再来复习一下Block作为返回值使用时的情况,先贴一小段热门第三方框架Masonry的官方sample code: [view1 mas ...