[译]开始学习webpack
寫在前面:
文章翻譯自petehunt大神的petehunt/webpack-howto,作為學習webpack的開始。fork了一份,翻譯后的在這里https://github.com/zjzhome/webpack-howto/blob/master/README-cn.md,有些地方翻譯的不好,也希望在閱讀后對于不好的地方對出評論或者在github上提個issue。
本文目標
本文講述如何使用webpack將事情做好,包括了我們在Instagram做的大多數(shù)事情,我們沒做的當然沒有:)
我的建議:以此文作為學習webpack的開始,然后再閱讀官方的文檔說明。
預備知識
- 要了解browserify,RequireJS或者其他類似的東東
- 了解以下事情的價值:
- 模塊劃分
- 異步加載
- 打包靜態(tài)資源,比如圖片和CSS
1、為什么使用webpack
-
和browserify類似,但可以將你的app劃分為不同的文件。 如果你的單頁應用你有多個頁面,用戶只需下載當前頁的代碼,如果他們離開此頁瀏覽其他頁面,不用再次下載那些通用的代碼。
-
通常情況下可以替代grunt和gulp,因為webpack可以構建和打包CSS,預處理CSS、可以編譯為JS的語言和圖片等等。
webpack支持AMD和CommonJS以及其他的模塊系統(tǒng)(Angular、ES6)。如果你不知道用哪種,使用CommonJS。
2、對于使用Browserify的童鞋
下面的兩個命令是等價的:
browserify main.js > bundle.js webpack main.js bundle.js不過,webpack比browserify更加給力,一般情況下,我們會創(chuàng)建webpack.config.js來保證條理性。
// webpack.config.js module.exports = {entry: './main.js',output: {filename: 'bundle.js' } };這完全是我們熟悉的JS,所以隨意將揮灑你的代碼。
3、如果調(diào)用webpack
切換到包含webpack.config.js的目錄, 運行:
- ?webpack??構建一次,開發(fā)環(huán)境下使用
- ?webpack -p??構建一次,生產(chǎn)環(huán)境使用(壓縮)
- ?webpack --watch??持續(xù)構建生產(chǎn)環(huán)境下使用(構建速度快)
- ?webpack -d??生成sourcemap
4、可編譯為JS的語言
webpack中和browserify轉換器以及RequireJS中的插件等價的是loader。下面展示了如何讓webpack支持加載CoffeeScript和Facebook JSX+ES6(你需要首先?npm install babel-loader coffee-loader?)):
// webpack.config.js module.exports = {entry: './main.js',output: {filename: 'bundle.js' },module: {loaders: [{ test: /\.coffee$/, loader: 'coffee-loader' },{ test: /\.js$/, loader: 'babel-loader' }]} };為了在加載文件的時候不必生命文件擴展名,你必須加上?resolve.extensions?這個參數(shù)來告訴webpack該尋找哪些文件.
// webpack.config.js module.exports = {entry: './main.js',output: {filename: 'bundle.js' },module: {loaders: [{ test: /\.coffee$/, loader: 'coffee-loader' },{ test: /\.js$/, loader: 'babel-loader' }]},resolve: {// you can now require('file') instead of require('file.coffee')extensions: ['', '.js', '.json', '.coffee'] } };5、樣式和圖片
首先,在你的代碼中使用require()來引入你的靜態(tài)資源。
require('./bootstrap.css'); require('./myapp.less');var img = document.createElement('img'); img.src = require('./glyph.png');當你引入CSS(或者less等),webpack會將CSS作為字符串打包到JS中,然后?require()?會在頁面中插入?<style>?標簽。當引入圖片資源的時候,webpack會將圖片地址打包進JS,?require()?返回圖片地址。
但是你要告訴webpack怎么做:
// webpack.config.js module.exports = {entry: './main.js',output: {path: './build', // This is where images AND js will gopublicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. imagesfilename: 'bundle.js'},module: {loaders: [{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders{ test: /\.css$/, loader: 'style-loader!css-loader' },{test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} // inline base64 URLs for <=8k images, direct URLs for the rest ]} };6、特征標識
有些代碼我們只想用在開發(fā)環(huán)境(比如日志)或者內(nèi)部的服務器(比如處于內(nèi)測的未發(fā)布產(chǎn)品特性)。在你的代碼里,使用以下幾個變量:
if (__DEV__) {console.warn('Extra logging'); } // ... if (__PRERELEASE__) {showSecretFeature(); }然后告訴webpack這些全局變量:
// webpack.config.js// definePlugin takes raw strings and inserts them, so you can put strings of JS if you want. var definePlugin = new webpack.DefinePlugin({__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),__PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false')) });module.exports = {entry: './main.js',output: {filename: 'bundle.js' },plugins: [definePlugin] };然后你可以在命令行里使用BUILD_DEV=1 BUILD_PRERELEASE=1 webpack命令構建,不過注意因為webpack -p命令會去清除無用的代碼,所有抱在這些代碼塊里的代碼都會被刪除,所以不要泄露私密特性或字符串。
7、多入口
假設你有一個用戶資料頁面和一個訂閱頁面,用戶在瀏覽資料頁面的你不想用戶下載訂閱頁面的代碼。所以要打多個包,為每一個頁面創(chuàng)建一個“主要模塊”(也叫作入口):
// webpack.config.js module.exports = {entry: {Profile: './profile.js',Feed: './feed.js'},output: {path: 'build',filename: '[name].js' // Template based on keys in entry above } };對于資料頁,在頁面插入?<script src="build/Profile.js"></script>?,訂閱頁面也是一樣。
8、優(yōu)化通用代碼
訂閱頁面和資料頁面共用許多代碼(像React以及其他的樣式和組件等)。webpack可以抽出他們共用的代碼,然后打一個通用包在各個頁面緩存。
// webpack.config.jsvar 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' // Template based on keys in entry above },plugins: [commonsPlugin] };在上一步的script標簽之前加上?<script src="build/common.js"></script>?,然后盡情享受免費的高速緩存吧。
9、異步加載
CommonJS是同步的,但是Webpack提供一個方法來異步的指定依賴。這在客戶端路由中很有用,每個頁面都需要路由,你不想直到你真正需要他們的時候才下載相關功能。
指定你想異步加載的分割點,比如:
if (window.location.pathname === '/feed') {showLoadingState();require.ensure([], function() { // this syntax is weird but it works hideLoadingState();require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available. }); } else if (window.location.pathname === '/profile') {showLoadingState();require.ensure([], function() {hideLoadingState();require('./profile').show();}); }webpack會做接下來的工作,并且產(chǎn)生額外的塊文件,然后加載他們。
當你加載這些文件到html的script標簽,webpack假定他們在根目錄,你可以通過?output.publicPath?來定義:
// webpack.config.js output: {path: "/home/proj/public/assets", //path to where webpack will build your stuffpublicPath: "/assets/" //path that will be considered when requiring your files }其他資源
看一下真實的案例:一個成功的團隊是如何使用webpack的。這是Pete Hunt在全球開源大會上關于Intagram使用的webpack的討論:http://youtu.be/VkTCL6Nqm6Y。
FAQ
webpack看起來不是模塊化的
webpack是嚴格模塊化的。和browserify和requirejs等替代選擇工具相比,webpack的偉大之處在于在構建過程中他讓插件將自己注入到盡可能多的地方。webpack很多看似內(nèi)建的功能只是默認加載的插件,他們是可以重寫的(比如CommonJS的require()語法分析器)。
轉載于:https://www.cnblogs.com/zjzhome/p/4951570.html
總結
以上是生活随笔為你收集整理的[译]开始学习webpack的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebConfig配置 文件加密处理
- 下一篇: Filter高级开发