webpack 的作用
- 把你的应用拆分成多个文件;
- 可以构建打包 css、预处理css、编译js和图片等;
- 它支持 AMD 和 CommonJS,以及其他的模块系统(Angular, ES6)。
起步
webpack.config.js 文件
module.exports = { entry: './main.js', output: { filename: 'bundle.js' } }
调用 webpack
- webpack 开发环境下编译
- webpack -p 产品编译及压缩
- webpack --watch 开发环境下持续的监听文件变动来进行编译(非常快)
- webpack -d 引入 source maps
编译 js
module.exports = { entry: './main.js', output: { filename: 'bundle.js' } module: { loaders: [ { test: /\.coffee$/, loader: 'coffee-loader' }, { test: /\.js$/, loader: 'babel-loader', query:{ presets: ['es2015', 'react'] } } ] } }
// 如果希望在 require 文件时省略文件的扩展名, // 只需要在 webpack.config.js 中添加 resolve.extensions 来配置 module.exports = { entry: './main.js', output: { filename: 'bundle.js' } module: { loaders: [ { test: /\.coffee$/, loader: 'coffee-loader' }, { test: /\.js$/, loaders: 'babel-loader', query: { presets: ['es2015', 'react'] } } ] }, resolve: { // 现在 require 文件的时候可以直接使用 require('file), 不用使用 require('file.js') extensions: ['', '.js', '.json', '.coffee'] } }
css 样式和图片的加载
module.exports = { entry: './main.js', output: { path: './build', // 图片和 js 文件会放在这 publicPath: 'http://mycdn.com/', // 这里用来生成图片的地址 filename: 'bundle.js' }, module: { loaders: [ { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' // 用 ! 去链式调用 loader }, { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.(png|jpg)$/, loader: 'url?limit=8192' // 内联的 base64 的图片地址,图片要小于 8k,直接的 url 的地址则不解析 } ] }, resolve: { extensions:['', '.js', '.json', '.coffee'] } };
功能标识
项目中有些代码我们只为在开发环境(例如日志)或者是内部测试环境(还没有发布的新功能)中使用,那就需要引入下面这些魔法全局变量:
if(__DEV__) { console.warn('Extra logging'); } if(__PRERELEASE__) { showSecrectFeature(); }
var definePlugin = new webpack.definePlugins({ __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')), __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'true')) }); module.exports = { entry: './main.js', output: { filename: 'bundle.js', } plugins: [definePlugin] }
多个入口文件
如果你有两个页面:profile 和 feed。如果你希望用户访问 profile 页面时不加载 feed 页面的代码,那就需要生成多个 bundles 文件:为每个页面创建自己的 'main module'(入口文件)
module.exports = { entry: { Profile: './profile.js', Feed: './feed.js' }, output: { path: 'build', filename: '[name].js' // name 基于上边 entry 定义的 key } };
优化通用代码
Feed 和 Profile 页面存在大量通用代码(比如 React、公共的样式和组件等等)。webpack 可以抽离页面间公共的代码,生成一个公共的 bundle文件, 供两个页面缓存使用:
var webpack = require('webpack'); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); // 引入插件 module.exports = { entry: { Profile: './profile.js', Feed: './feed.js' }, output: { path: 'build', filename: '[name].js' // name 为上面 entry 的 key 值 }, plugins: [commonsPlugin] };
异步加载
虽然 CommonJS 是同步加载的,但是 webpack 也提供了异步加载的方式。这对于单页应用中使用的客户端路由非常有用。当真正路由到了某个页面的时候,它的代码才会被加载下来。
if(window.location.pathname === './feed') { showLoadingState(); require.ensure([], function(){ hideLoadingState(); require('./feed').show(); // 当这个函数调用的时候,此模块一定已经被同步加载下来了 }); } else if (window.location.pathname === './profile') { showLoadingState(); require.ensure([], function() { hideLoadingState(); require('./profile').show(); }); } // webpack.config.js output: { path: "/home/proj/public/assets", // webpack 的 build 路径 publicPath: "/assets/" // require 的路径 }