已經(jīng)看過這一節(jié)的朋友,可以看Webpack+React+多語言(二) 插件配置+多語言
github地址:webpack-react-language
關(guān)鍵字:react 多語言 國際版 React-intl
移動端網(wǎng)站需要重構(gòu),當(dāng)前的想法是使用webpack+react來重構(gòu)移動端,當(dāng)然,是需要支持多語言的。
-
1.創(chuàng)建一個項目:webpack-react-language
這個項目名字有點長,我主要是為了與本地其他的項目區(qū)別開來
目錄結(jié)構(gòu)
|- build
|-- index.html
|-- bundle.js(該文件是webpack打包后生成的)
|- app
|-- components
|--- Dialog.jsx
|-- main.js
|- package.json(第二步生成)
|- webpack.config.js(第四步生成)
-
2.創(chuàng)建package.json
npm init
-
3.安裝webpack
//全局安裝webpack,優(yōu)點是打包時可以直接輸webpack命令
npm install -g webpack
//在本項目中安裝webpack,--save-dev的意思是將依賴寫入項目的package.json文件
npm install --save-dev webpack
-
4.創(chuàng)建webpack.config.js配置文件
module.exports = {
entry: __dirname + "/app/main.js",//唯一入口文件,就像Java中的main方法
output: {//輸出目錄
path: __dirname + "/build",//打包后的js文件存放的地方
filename: "bundle.js"http://打包后的js文件名
}
};
運行webpack
,webpack非全局安裝需輸入node_modules/.bin/webpack
看到以上提示說明打包成功了,可以看到build目錄下的bundle.js里多了很多自動生成的代碼,但預(yù)覽index.html卻什么都沒有看到,這是因為還沒有往頁面中寫入內(nèi)容。
-
5.更方便地執(zhí)行打包命令
執(zhí)行類似于node_modules/.bin/webpack
這樣的命令其實是比較煩人且容易出錯的,不過值得慶幸的是npm可以引導(dǎo)任務(wù)執(zhí)行,對其進行配置后可以使用簡單的npm start命令來代替這些繁瑣的命令。在package.json中對npm的腳本部分進行相關(guān)設(shè)置即可,設(shè)置方法如下。
打開package.json,找到script代碼塊,更改為:
"scripts": {
"build": "webpack"
或者
"start":"webpack"
}
但是start是一個特殊的腳本名稱,如果腳本名稱不是start,則需要npm run (script name)
,如npm run build
,但是start可以直接執(zhí)行npm start
-
6.使用Source Maps,使調(diào)試更容易
devtool選項 | 配置結(jié)果 |
---|---|
source-map | 在一個單獨的文件中產(chǎn)生一個完整且功能完全的文件。這個文件具有最好的source map,但是它會減慢打包文件的構(gòu)建速度 |
cheap-module-source-map | 在一個單獨的文件中生成一個不帶列映射的map,不帶列映射提高項目構(gòu)建速度,但是也使得瀏覽器開發(fā)者工具只能對應(yīng)到具體的行,不能對應(yīng)到具體的列(符號),會對調(diào)試造成不便 |
eval-source-map | 使用eval打包源文件模塊,在同一個文件中生成干凈的完整的source map。這個選項可以在不影響構(gòu)建速度的前提下生成完整的sourcemap,但是對打包后輸出的JS文件的執(zhí)行具有性能和安全的隱患。不過在開發(fā)階段這是一個非常好的選項,但是在生產(chǎn)階段一定不要用這個選項 |
cheap-module-eval-source-map | 這是在打包文件時最快的生成source map的方法,生成的Source Map 會和打包后的JavaScript文件同行顯示,沒有列映射,和eval-source-map選項具有相似的缺點 |
正如上表所述,上述選項由上到下打包速度越來越快,不過同時也具有越來越多的負面作用,較快的構(gòu)建速度的后果就是對打包后的文件的的執(zhí)行有一定影響。
在學(xué)習(xí)階段以及在小到中性的項目上,eval-source-map是一個很好的選項,不過記得只在開發(fā)階段使用它,繼續(xù)上面的例子,進行如下配置
/webpack.config.js
module.exports = {
devtool: 'eval-source-map',//生成Source Maps,這里選擇eval-source-map
entry: __dirname + '/app/main.js',//唯一入口文件,__dirname是node.js中的一個全局變量,它指向當(dāng)前執(zhí)行腳本所在的目錄
output: {//輸出目錄
path: __dirname + '/build',//打包后的js文件存放的地方
filename: 'bundle.js'//打包后輸出的js的文件名
}
};
-
7.安裝React、Babel
npm install react --save-dev
npm install react-dom --save-dev
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react --save-dev
在webpack.config.js中
/webpack.config.js
module.exports = {
devtool: 'eval-source-map',//生成Source Maps,這里選擇eval-source-map
entry: __dirname + '/app/main.js',//唯一入口文件,__dirname是node.js中的一個全局變量,它指向當(dāng)前執(zhí)行腳本所在的目錄
output: {//輸出目錄
path: __dirname + '/build',//打包后的js文件存放的地方
filename: 'bundle.js'//打包后輸出的js的文件名
},
module: { //loaders加載器
loaders: [{
test: /\.(js|jsx)$/,//一個匹配loaders所處理的文件的拓展名的正則表達式,這里用來匹配js和jsx文件(必須)
exclude: /node_modules/,//屏蔽不需要處理的文件(文件夾)(可選)
loader: 'babel-loader'//loader的名稱(必須) 原來可以簡寫成babel,現(xiàn)在會提示報錯,需要寫全babel-loader,后續(xù)其他的loader也是一樣的處理
}]
}
};
在項目根目錄下新建.babelrc文件,沒錯你沒看錯,就是只有后綴名的文件,添加如下代碼:
//.babelrc
{
"presets": [
"react",
"es2015"
]
}
-
8.編寫頁面文件,為后續(xù)測試功能做準備
app/main.js
import React from 'react';
import ReactDom from 'react-dom';
import Dialog from './components/dialog.jsx';
ReactDom.render(
<Dialog />,
document.getElementById('content')
);
app/components/dialog.jsx
import React from 'react';
class Dialog extends React.Component {
render() {
return (
<div>Hello World!</div>
)
}
}
//導(dǎo)出組件
export default Dialog;
build/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
我使用的編輯器是webstorm,上述步驟完成之后,執(zhí)行npm start
,打包成功后,運行index.html,可以看到頁面上
-
9.安裝并啟用webpack-dev-server
執(zhí)行到這一步,基本的運作是可以了,但是每次修改文件之后,都需要重新打包,再運行,才可以看到新的內(nèi)容,如何能忍受這么low的執(zhí)行過程呢?
我們可以使用webpack-dev-server來搭建本地開發(fā)服務(wù)器,webpack-dev-server允許我們可以把本地項目跑在像nginx那樣的web服務(wù)器上,修改代碼后,立即可以看到變化;所見即所得,大大增加開發(fā)效率。
安裝webpack-dev-server
npm install webpack-dev-server -g
npm install webpack-dev-server --save-dev
更改packaje.json中的代碼塊
"scripts": {
"start": "webpack",
"dev": "webpack-dev-server --devtool eval --progress --colors --content-base build"
}
ps:dev里各屬性值的意思是:
- webpack-dev-server: 在 localhost:8080 建立一個 Web 服務(wù)器
- --devtool eval:為你的代碼創(chuàng)建源地址。當(dāng)有任何報錯的時候可以讓你更加精確地定位到文件和行號
- --progress: 顯示合并代碼進度
- --colors: 在命令行中顯示顏色
- --content-base build:指向設(shè)置的輸出目錄
在webpack.config.js中配置webpack-dev-server,在這里需要修改下entry的路徑,給它加一個webpack/hot/dev-server,這里會用到Hot Module Replacement(熱替換)插件,所以需要增加這個前綴,后文會提到,代碼如下:
//webpack.config.js
module.exports = {
devtool: 'eval-source-map',//生成Source Maps,這里選擇eval-source-map
entry: ['webpack/hot/dev-server', __dirname + '/app/main.js'],//唯一入口文件,__dirname是node.js中的一個全局變量,它指向當(dāng)前執(zhí)行腳本所在的目錄
output: {//輸出目錄
path: __dirname + '/build',//打包后的js文件存放的地方
filename: 'bundle.js'//打包后輸出的js的文件名
},
module: { //loaders加載器
loaders: [ {
test: /\.(js|jsx)$/,//一個匹配loaders所處理的文件的拓展名的正則表達式,這里用來匹配js和jsx文件(必須)
exclude: /node_modules/,//屏蔽不需要處理的文件(文件夾)(可選)
loader: 'babel'//loader的名稱(必須)
} ]
},
//webpack-dev-server配置
devServer: {
contentBase: './build',//默認webpack-dev-server會為根文件夾提供本地服務(wù)器,如果想為另外一個目錄下的文件提供本地服務(wù)器,應(yīng)該在這里設(shè)置其所在目錄(本例設(shè)置到"build"目錄)
colors: true,//在cmd終端中輸出彩色日志
historyApiFallback: true,//在開發(fā)單頁應(yīng)用時非常有用,它依賴于HTML5 history API,如果設(shè)置為true,所有的跳轉(zhuǎn)將指向index.html
inline: true,//設(shè)置為true,當(dāng)源文件改變時會自動刷新頁面
port: 8080,//設(shè)置默認監(jiān)聽端口,如果省略,默認為"8080"
process: true,//顯示合并代碼進度
}
};
在瀏覽器中打開http://localhost:8080/
,如果頁面上是空白的,沒有內(nèi)容,按F12打開控制臺,可以清除地看到錯誤提示:Uncaught Error: [HMR] Hot Module Replacement is disabled
現(xiàn)在我們來安裝和配置這個Hot Module Replacement。
新版本的webpack(當(dāng)前我使用的是webpack3.0),這樣配置會有問題。
如果用的不是webpack3,可以忽略下面這部分,直接看#10
新版webpack沿用上面的配置文件報錯
建議
1.webpack3的朋友,按下面的代碼配置,或者將webpack的版本退回我圖上的版本,進行操作。
2.推薦先看第十步的內(nèi)容,可以幫助大家了解下面代碼中的HotModuleReplacementPlugin
webpack3 配置
//webpack-dev-server配置
plugins: [
new webpack.HotModuleReplacementPlugin({
contentBase: './build',//默認webpack-dev-server會為根文件夾提供本地服務(wù)器,如果想為另外一個目錄下的文件提供本地服務(wù)器,應(yīng)該在這里設(shè)置其所在目錄(本例設(shè)置到"build"目錄)
colors: true,//在cmd終端中輸出彩色日志
historyApiFallback: true,//在開發(fā)單頁應(yīng)用時非常有用,它依賴于HTML5 history API,如果設(shè)置為true,所有的跳轉(zhuǎn)將指向index.html
inline: true,//設(shè)置為true,當(dāng)源文件改變時會自動刷新頁面
port: 8080,//設(shè)置默認監(jiān)聽端口,如果省略,默認為"8080"
process: true,//顯示合并代碼進度
})
]
-
10.Hot Module Replacement
Hot Module Replacement(HMR)是webpack里很有用的一個插件,它允許你在修改組件代碼后,自動刷新實時預(yù)覽修改后的效果。
在webpack中實現(xiàn)HMR也很簡單,只需要做兩項配置
1.在webpack配置文件中添加HMR插件;
2.在Webpack Dev Server中添加“hot”參數(shù);
不過配置完這些后,JS模塊其實還是不能自動熱加載的,還需要在你的JS模塊中執(zhí)行一個Webpack提供的API才能實現(xiàn)熱加載,雖然這個API不難使用,但是如果是React模塊,使用我們已經(jīng)熟悉的Babel可以更方便的實現(xiàn)功能熱加載。
整理下我們的思路,具體實現(xiàn)方法如下
- Babel和webpack是獨立的工具
- 二者可以一起工作
- 二者都可以通過插件拓展功能
- HMR是一個webpack插件,它讓你能瀏覽器中實時觀察模塊修改后的效果,但是如果你想讓它工作,需要對模塊進行額外的配額;
- Babel有一個叫做react-transform-hrm的插件,可以在不對React模塊進行額外的配置的前提下讓HMR正常工作;
在webpack.config.js中配置如下:
//webpack.config.js
var webpack = require('webpack')
module.exports = {
devtool: 'eval-source-map',//生成Source Maps,這里選擇eval-source-map
entry: ['webpack/hot/dev-server', __dirname + '/app/main.js'],//唯一入口文件,__dirname是node.js中的一個全局變量,它指向當(dāng)前執(zhí)行腳本所在的目錄
output: {//輸出目錄
path: __dirname + '/build',//打包后的js文件存放的地方
filename: 'bundle.js'//打包后輸出的js的文件名
},
module: { //loaders加載器
loaders: [ {
test: /\.(js|jsx)$/,//一個匹配loaders所處理的文件的拓展名的正則表達式,這里用來匹配js和jsx文件(必須)
exclude: /node_modules/,//屏蔽不需要處理的文件(文件夾)(可選)
loader: 'babel'//loader的名稱(必須)
} ]
},
plugins: [
new webpack.HotModuleReplacementPlugin()//熱模塊替換插件
],
//webpack-dev-server配置
devServer: {
contentBase: './build',//默認webpack-dev-server會為根文件夾提供本地服務(wù)器,如果想為另外一個目錄下的文件提供本地服務(wù)器,應(yīng)該在這里設(shè)置其所在目錄(本例設(shè)置到"build"目錄)
colors: true,//在cmd終端中輸出彩色日志
historyApiFallback: true,//在開發(fā)單頁應(yīng)用時非常有用,它依賴于HTML5 history API,如果設(shè)置為true,所有的跳轉(zhuǎn)將指向index.html
inline: true,//設(shè)置為true,當(dāng)源文件改變時會自動刷新頁面
port: 8080,//設(shè)置默認監(jiān)聽端口,如果省略,默認為"8080"
process: true,//顯示合并代碼進度
}
};
現(xiàn)在可以正常工作了,運行npm run dev
,待命令行提示webpack: bundle is now VALID
后,在瀏覽器中輸入http://localhost:8080
,可以看到,正常顯示Hello World
如果覺得這樣不放心,讓我們進行如下額外配置
安裝react-transform-hmr,在不對React模塊進行額外的配置的前提下讓HMR正常工作
npm install --save-dev babel-plugin-react-transform react-transform-hmr
在.babelrc文件里配置babel,注意這里有一堆括號,別寫錯了
//.babelrc
{
"presets": [
"react",
"es2015"
],
"env": {
"development": {
"plugins": [
[
"react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": [ "react" ],
"locals": [ "module" ]
}]
}
]
]
}
}
}
至此,已經(jīng)用webpack構(gòu)建好了React項目的基礎(chǔ)依賴,可以愉快的開發(fā)React程序了。
由于內(nèi)容太多,于是將本文分成了多個部分,下一部分Webpack+React+多語言(二) 插件配置+多語言
github地址:webpack-react-language