Webpack構建基本的React+ES6專案 --- 圖片的路徑與打包
webpack是最近比較火的構建工具,搭配上同樣比較火的ReacJS與ES6(ES2015)一定是現在很多潮流 programmer 的追求。 廢話不多,下面就就看下如何從0搭起我們的構建工具。
http://www.cnblogs.com/ghost-xyx/p/5812902.html
安裝
全域性安裝webpack,如果安裝後還是提示沒有webpack commond,可以嘗試通過超級管理員身份安裝。
$ npm install webpack -g
$ sudo npm install webpack -g
或者在專案裡進行安裝
$ npm install webpack --save-dev
配置
建立目錄
index.js檔案內容:
document.write('Hello Webpack');
生成package.json檔案,-y為生成預設內容
$ npm init
$ npm init -y
建立webpack.config.js檔案
var webpack = require('webpack'); module.exports = { entry: './app/index.js', //入口 output: { //輸出 path: 'bundle', publicPath: '/static/', filename:'bundle.js' }, module: { loaders: [ //載入器 {test: /\.css$/, loader: 'style-loader!css-loader' }, {test: /\.js$/, loader: 'babel-loader'}, {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} ] } }
注意輸出中有一個path屬性和一個publicPath屬性,這二者的區別在於path為本地路徑,publicPath是你啟用伺服器(webpack-dev-server/react-hot-loader)時的路徑。
在webpack中所以的資源都需要通過載入器載入,多個載入器之間用 ! 隔開,其中-loader的字尾是可以省略的。
webpack.config檔案中每個申明的載入器都需要安裝,否則執行會報錯:
$ npm install style-loader css-loader --save-dev
鑑於一個專案中會有N多個loader,通常將這些loader寫入package.json檔案的devDependencies屬性中,之後通過 $ npm install 命令一次全部安裝。
這裡選用 babel 載入器來載入我們的JS檔案,使用它最少需要安裝 babel-core 與 babel-loader。如果想用 babel 解析 ES6 和 React,還需要安裝上圖中的 babel-preset-es2015 和 babel-preset-react,這個後面再說。
執行
上述配置工作完成後我們來啟動webpack
$ webpack
執行該命令後,專案下多了個 bundle 資料夾,裡面有輸出的 bundle.js 檔案
在index.html中引入編譯過的bundle.js
<script src="../bundle/bundle.js"></script>
執行index.html檔案
這樣就完成了基本配置並跑起了第一個DEMO,看下其他比較實用的命令
$ webpack --config xxx.js //使用另一份config檔案 $ webpack --watch //自動監聽打包 $ webpack -p //壓縮混淆指令碼 $ webpack -d //生成map對映檔案
初上手第二個和第三個命令比較常用,--watch 使得我們不用每更改一次程式碼就執行一次 $ webpack。-p會壓縮打包檔案,使得體積減小很多,通常將壓縮後的檔案釋出到線上。
webpack中,所有資源都是通過模組化的方式引入的。其同時支援commonjs和AMD的語法。接下來我們引入css檔案。同時別忘記安裝 style-loader 與 css-loader。
style.css 內容
body { color: red; }
index.js 內容
require('./style.css');
document.write('Hello Webpack');
結果
支援ES6
上文說過要支援ES6,還需要安裝babel-preset-2015。
$ npm install babel-preset-es2015
安裝好之後修改webpack.config檔案如下:
{ test: /\.js$/, loader: 'babel-loader', query: { presets: ['es2015'] } }
這裡我們通過在app目錄下建立 app.js 檔案:
let a = 'ES6 is working!'; export default a;
修改 index.js
import './style.css'; import text from './app.js'; alert(text); document.write('Hello Webpack');
結果
支援ReactJS
首先安裝 react 與 babel-preset-react
$ npm install react react-dom babel-preset-react --save-dev
修改 webpack.config,在preset屬性中新增react一項。
{ test: /\.js$/, loader: 'babel-loader', query: { presets: ['es2015', 'react'] } }
修改 app.js 內容
import React, { Component } from 'react'; class App extends Component { render() { return ( <h1>React is working!</h1> ); } } export default App;
修改 index.js 內容
import './style.css'; import React from 'react'; import ReactDOM from 'react-dom'; import Title from './app.js'; ReactDOM.render(<Title />, document.body);
結果
這樣我們就可以在靜態專案裡同時使用ES6與React了,下面我們看看如果通過本地伺服器實現瀏覽器自動重新整理。
如果你專案中並沒有用到React,你可以通過webpack-dev-server來實現自動重新整理。如果使用了React,可以使用量身定做的React-hot-loader。
下面來依次說說二者。
webpack-dev-server
安裝
npm install webpack-dev-server --save-dev
更改 index.html檔案
<script src="static/bundle.js"></script>
此時的路徑就是 webpack.config 檔案中 publickPath 中設定的
執行
webpack-dev-server
webpack-dev-server --port 3000
服務預設啟動8080埠,通過--port命令可以更改埠。這樣我們就可以在localhost:3000/index.html訪問到我們的頁面了。
熱重新整理
webpack的熱重新整理分為iframe模式與inline模式
iframe模式操作要簡單許多,其並不需要更改配置,只需要訪問localhost:3000/webpack-dev-server/index.html。
現在當我們更改 js 檔案時瀏覽器就會自動重新整理。
inline模式有興趣可以去參考文件。
react-hot-loader
安裝
npm install react-hot-loader --save-dev
更改 webpack.config 檔案,並引入外掛。
entry: [ 'webpack-dev-server/client?http://localhost:2000', 'webpack/hot/only-dev-server', './js/index.js' ], plugins: [ new webpack.HotModuleReplacementPlugin() ], module: { loaders: [{ test: /\.js$/, loaders: ['babel', 'react-hot'], }] }
建立 server.js 檔案
var webpack = require('webpack'), WebpackDevServer = require('webpack-dev-server'), config = require('./webpack.config'); new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, hot: true, historyApiFallback: true }).listen(3000, 'localhost', function (err, result) { if (err) { return console.log(err); } console.log('Listening at http://localhost:3000/'); });
使用命令啟動
node server.js
也可以寫入 package.json 中
"scripts": { "start": "node server.js" }
執行
npm start
這樣React專案就可以實現熱重新整理了,不過在實際使用過程中還是會遇到各種坑。這裡引入個完整的官方DEMO,親測可用,文件也非常簡潔明瞭。
https://github.com/gaearon/react-hot-boilerplate
剛開始用webpack的同學很容易掉進圖片打包這個坑裡,比如打包出來的圖片地址不對或者有的圖片並不能打包進我們的目標資料夾裡(bundle)。下面我們就來分析下在webpack專案中圖片的應用場景。
在實際生產中有以下幾種圖片的引用方式:
1. HTML檔案中img標籤的src屬性引用或者內嵌樣式引用
<img src="photo.jpg" /> <div style="background:url(photo.jpg)"></div>
2. CSS檔案中的背景圖等設定
.photo { background: url(photo.jpg); }
3. JavaScript檔案中動態新增或者改變的圖片引用
var imgTempl = '<img src="photo.jpg" />'; document.body.innerHTML = imgTempl;
4. ReactJS中圖片的引用
import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { render() { return (<img src='photo.jpg' />); } } ReactDom.render(<App />, document.querySelector('#container'));
url-loader
在 webpack 中引入圖片需要依賴 url-loader 這個載入器。
安裝:
npm install url-loader --save-dev
當然你可以將其寫入配置中,以後與其他工具模組一起安裝。
在 webpack.config.js 檔案中配置如下:
module: { loaders: [ { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } ] }
test 屬性代表可以匹配的圖片型別,除了 png、jpg 之外也可以新增 gif 等,以豎線隔開即開。
loader 後面 limit 欄位代表圖片打包限制,這個限制並不是說超過了就不能打包,而是指當圖片大小小於限制時會自動轉成 base64 碼引用。上例中大於8192位元組的圖片正常打包,小於8192位元組的圖片以 base64 的方式引用。
url-loader 後面除了 limit 欄位,還可以通過 name 欄位來指定圖片打包的目錄與檔名:
module: { loaders: [ { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ] }
上例中的 name 欄位指定了在打包根目錄(output.path)下生成名為 images 的資料夾,並在原圖片名前加上8位 hash 值。
例:工程目錄如下
在 main.css 中引用了同級 images 資料夾下的 bg.jpg 圖片
background-image: url(./images/bg.jpg);
通過之前的配置,使用 $ webpack 命令對程式碼進行打包後生成如下目錄
打包目錄中,css 檔案和 images 資料夾保持了同樣的層級,可以不做任務修改即能訪問到圖片。區別是打包後的圖片加了 hash 值,bundle.css 檔案裡引入的也是有hash值的圖片。
background-image: url(images/f593fbb9.bg.jpg);
(上例中,使用了單獨打包css的技術,只是為了方便演示)
publicPath
output.publicPath 表示資源的釋出地址,當配置過該屬性後,打包檔案中所有通過相對路徑引用的資源都會被配置的路徑所替換。
output: { path: 'dist', publicPath: '/assets/', filename: 'bundle.js' }
main.css
background-image: url(./images/bg.jpg);
bundle.css
background-image: url(/assets/images/f593fbb9.bg.jpg);
該屬性的好處在於當你配置了圖片 CDN 的地址,本地開發時引用本地的圖片資源,上線打包時就將資源全部指向 CDN 了。
但是要注意,如果沒有確定的釋出地址不建議配置該屬性,否則會讓你打包後的資源路徑很混亂。
JS中的圖片
初用 webpack 進行專案開發的同學會發現:在 js 或者 react 中引用的圖片都沒有打包進 bundle 資料夾中。
正確寫法應該是通過模組化的方式引用圖片路徑,這樣引用的圖片就可以成功打包進 bundle 資料夾裡了
js
var imgUrl = require('./images/bg.jpg'), imgTempl = '<img src="'+imgUrl+'" />'; document.body.innerHTML = imgTempl;
react
render() { return (<img src={require('./images/bg.jpg')} />); }
HTML中的圖片
由於 webpack 對 html 的處理不太好,打包 HTML 檔案中的圖片資源是相對來說最麻煩的。這裡需要引用一個外掛—— html-withimg-loder
$ npm install html-withimg-loader --save-dev
webpack.config.js 新增配置
module: { loaders: [ { test: /\.html$/, loader: 'html-withimg-loader' } ] }
在 bundle.js 中引用 html 檔案
import '../index.html';
這樣 html 檔案中的圖片就可以被打包進 bundle 資料夾裡了。
感謝您的瀏覽,希望能有所幫助