Tip:css
本文是 webpack-howto 的原文,我以爲這篇文章寫得很是好,確實算是目前學習 webpack 入門的必讀文章。直接收錄之。node
這是一本教你如何應用webpack到你的項目中的工具書。它包含了咱們在Instagram
中用到的絕大多數的內容。react
個人建議:這個教程做爲你第一個webpack
的文檔,學習完之後去看它的官方文檔,瞭解更詳細的說明。webpack
browserify
、RequireJS
的東西它支持AMD和CommonJS,以及其餘的模塊系統(Angular, ES6)。若是你不太熟悉如何使用,就用CommonJS吧。git
下面的命令是等價的:es6
browserify main.js > bundle.js
webpack main.js bundle.js
然而,webpack要比Browserify強大。因此通常狀況下你須要創建一個webpack.config.js
文件來配置webpack。github
// webpack.config.js module.exports = { entry: './main.js', output: { filename: 'bundle.js' } };
這就是單純的JS,全部寫這個配置文件毫無壓力。web
選擇一個目錄下有webpack.config.js
文件的文件夾,而後運行下面的命令:npm
webpack
開發環境下編譯webpack -p
產品編譯及壓縮
webpack --watch
開發環境下持續的監聽文件變更來進行編譯(很是快!)webpack -d
引入 source mapswebpack能夠和browserify、RequireJS同樣做爲一個loader(加載工具)來使用。下面咱們來看下如何使用webpack去加載、編譯CoffeeScript和JSX+ES6。(這裏你必須先 npm install babel-loader coffee-loader
):json
你也要看下babel-loader的介紹,它會做爲一個開發環境下的依賴加載到咱們的項目中(run npm install babel-core babel-preset-es2015 babel-preset-react
)
// webpack.config.js module.exports = { entry: './main.js', // 入口文件 output: { filename: 'bundle.js' // 打包輸出的文件 }, module: { loaders: [ { test: /\.coffee$/, // test 去判斷是否爲.coffee的文件,是的話就是進行coffee編譯 loader: 'coffee-loader' }, { test: /\.js$/, // test 去判斷是否爲.js,是的話就是進行es6和jsx的編譯 loader: 'babel-loader', query: { presets: ['es2015', 'react'] } } ] } };
若是你但願在require文件時省略文件的擴展名,只須要在webpack.config.js中添加 resolve.extensions
來配置。
// webpack.config.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'] } } ] }, resolve: { // 如今你require文件的時候能夠直接使用require('file'),不用使用require('file.coffee') extensions: ['', '.js', '.json', '.coffee'] } };
首先你須要用require()
去加載你的靜態資源(named as they would with node's require()
):
require('./bootstrap.css'); require('./myapp.less'); var img = document.createElement('img'); img.src = require('./glyph.png');
當你require了CSS(less或者其餘)文件,webpack會在頁面中插入一個內聯的<style>
,去引入樣式。當require圖片的時候,bundle文件會包含圖片的url,並經過require()
返回圖片的url。
可是這須要你在webpack.config.js
作相應的配置(這裏仍是使用loaders)
// webpack.config.js 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-loader?limit=8192'} // 內聯的base64的圖片地址,圖片要小於8k,直接的url的地址則不解析 ] } };
項目中有些代碼咱們只爲在開發環境(例如日誌)或者是內部測試環境(例如那些沒有發佈的新功能)中使用,那就須要引入下面這些魔法全局變量(magic globals):
if (__DEV__) { console.warn('Extra logging'); } // ... if (__PRERELEASE__) { showSecretFeature(); }
同時還要在webpack.config.js中配置這些變量,使得webpack可以識別他們。
// webpack.config.js // definePlugin 會把定義的string 變量插入到Js代碼中。 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
會刪除全部無做用代碼,也就是說那些包裹在這些全局變量下的代碼塊都會被刪除,這樣就能保證這些代碼不會因發佈上線而泄露。
若是你有兩個頁面:profile和feed。若是你但願用戶訪問profile頁面時不加載feed頁面的代碼,那就須要生成多個bundles文件:爲每一個頁面建立本身的「main module」(入口文件)。
// webpack.config.js module.exports = { entry: { Profile: './profile.js', Feed: './feed.js' }, output: { path: 'build', filename: '[name].js' // name是基於上邊entry中定義的key } };
在profile頁面中插入<script src="build/Profile.js"></script>
。feed也同樣。
Feed和Profile頁面存在大量通用代碼(好比React、公共的樣式和組件等等)。webpack能夠抽離頁面間公共的代碼,生成一個公共的bundle文件,供這兩個頁面緩存使用:
// webpack.config.js 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' // 爲上面entry的key值 }, plugins: [commonsPlugin] };
在上一步引入本身的bundle以前引入<script src="build/common.js"></script>
雖然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,它會爲你生成並加載這些額外的 chunk 文件。
webpack 默認會從項目的根目錄下引入這些chunk文件。你也能夠經過 output.publicPath
來配置chunk文件的引入路徑
// webpack.config.js output: { path: "/home/proj/public/assets", // webpack的build路徑 publicPath: "/assets/" // 你require的路徑 }
看一個真實的例子,看看他們是怎麼使用webpack。這是Pete Hunt在Instagram.com中談論webpack的視頻。
相比較browserify和browserify,在你的項目中大量的使用webpack插件才能體現出webpack的優點。當使用了插件後,代碼纔會被複寫。其他的都是默認加載。