webpack+react+redux+es6開發模式---續

1、前言

  以前介紹了webpack+react+redux+es6開發模式 ,這個項目對於一個獨立的功能節點來講是沒有問題的。假如伴隨着源源不斷的需求,前段項目會涌現出更多的功能節點,須要獨立部署運行。爲了更好地管理這些獨立的功能節點,咱們須要利用webpack進行單獨的打包處理,針對不一樣的功能節點生成不一樣的配置文件html

2、項目結構

  1.項目demo目錄圖片示例

  

  2.apps目錄圖片示例(project1和project2分別表示兩個不一樣的功能節點)

   

3、npm-scripts 命令

  package.json部分示前端

  

  接下來,會說明下每一個命令的用途。java

4、webpack的dll功能

  Dll是Webpack最近新加的功能, 我簡單介紹一下。node

  Dll就是一個純純的依賴庫,它自己不能運行,是用來給你的app引用的。react

  打包dll的時候,Webpack會將全部包含的庫作一個索引,寫在一個manifest文件中,而引用dll的代碼(dll user)在打包的時候,只須要讀取這個manifest文件,就能夠了。webpack

這麼一來有幾個好處:git

  • Dll打包之後是獨立存在的,只要其包含的庫沒有增減、升級,hash也不會變化,所以線上的dll代碼不須要隨着版本發佈頻繁更新。es6

  • App部分代碼修改後,只須要編譯app部分的代碼,dll部分,只要包含的庫沒有增減、升級,就不須要從新打包。這樣也大大提升了每次編譯的速度。github

  • 假設你有多個項目,使用了相同的一些依賴庫,它們就能夠共用一個dll。web

  1.webpack.config.js中關於Dll的配置以下

  

  webpack.DllPlugin 的選項中, path 是manifest文件的輸出路徑; name 是dll暴露的對象名,要跟 output.library 保持一致; context 是解析包路徑的上下文,這個要跟接下來配置的dll user一致。

  如何進行打包呢,接下來就會用到上面提到的scripts命令(package.json文件中)。這裏要說的命令是"dll project1"對應的命令,以下。

webpack --display-error-details --progress --colors -p --config config.project1.dll.js

  該命令會加載config.project1.dll.js,對應的配置內容以下:

var config = require('./webpack.config');
module.exports = config.webpackdll({
    key:'project1'
    //根目錄
    ,rootPath:__dirname
});

  執行"npm run dll project1"命令,會輸出兩個文件一個是打包好的vendor.dll.js,一個就是manifest-vendor.json。因爲在config.project1.dll.js中配置的key值是功能節點的名稱"project1",因此生成的兩個文件在apps/project1目錄下,以下圖所示。

  

  其中manifest-vendor.json大體的樣子以下圖所示。

  

  Webpack將每一個庫都進行了編號索引,以後的dll user能夠讀取這個文件,直接用id來引用。文件內容中的"name"對應的值'dll_vendor' 就是 webpack.config.js中關於Dll的配置中 DllPlugin 中關於 name值的配置,以下所示。

new webpack.DllPlugin({
    path: options.manifestPath||'apps/'+key+'/manifest-[name].json',//manifest.json 文件的輸出路徑,這個文件會用於後續的業務代碼打包
    name: options.manifestName||'dll_[name]',// dll 暴露的對象名,要跟 output.library 保持一致
    context: options.manifestContext||rootPath,//解析包路徑的上下文,這個要跟接下來配置的 webpack.config.js 一致
}),

  2.關於Dll user的配置

  

  DllReferencePlugin 的選項中, context 須要跟以前保持一致,這個用來指導Webpack匹配manifest中庫的路徑; manifest 用來引入剛纔輸出的manifest文件。

 

  參考:http://www.tuicool.com/articles/NZ77re

5、開發環境

  開發人員開發項目的時候,使用 webpack devserver 啓動項目。這裏接着說一個命令"dev-project1", 以下。

webpack-dev-server --devtool eval --display-error-details --progress --colors --hot --inline --config config.project1.js 

  config.project1.js的配置內容以下。

var config = require('./webpack.config');
//打印啓動信息
config.initPrint(__filename);
var path = require('path'); 
var cwd = process.cwd();//返回運行當前腳本的工做目錄的路徑
var baseRoot = "./apps/project1/src/"
var options = {
  //定義標識名(若是有多個應用,能夠寫成 應用的名稱)
  key : 'project1',
  //定義各模塊的入口
  modules : {
    bundle: './project1-index.js'//入口
  }
  //根目錄
  ,rootPath:__dirname
  //webpack-dev-server啓動的端口
  ,port:8000
  //相對路徑
  //,path: path.join(__dirname, '')
  //編譯後的路徑
  //,filename: '[name]/build/bundle.js'
  //定義各類加載器
  //,loaders: []
  //定義各類插件
  //,plugins:[]
  //定義路徑別名,即:require(alias)
  , alias: {
    "styles": path.join(cwd, baseRoot + "styles"),
    "less": path.join(cwd, baseRoot + "styles/less"),
    "actions": path.join(cwd,baseRoot + "actions"),
    "constants": path.join(cwd, baseRoot + "constants"),
    "images": path.join(cwd, baseRoot + "images"),
    "reducers": path.join(cwd, baseRoot + "reducers"),
    "stores": path.join(cwd, baseRoot + "stores"),
    "modules": path.join(cwd, baseRoot + "modules"),
    "components": path.join(cwd, baseRoot + "components"),
    "utils": path.join(cwd, baseRoot + "utils"),
    "routes": path.join(cwd, baseRoot + "routes"),
    "trd": path.join(cwd, baseRoot + "trd"),
  }
}
//服務端產出路徑
if(process.env.NODE_ENV==='prod') {//生產環境
  options.publicPath = '/project1-front';
}else if(process.env.NODE_ENV==='test') {//測試環境
  //options.publicPath = '/icop-sampleapp-frontend';
}else{//本地開發環境
}

//構建webpack配置
module.exports = config.webpack(options);

  配置中的註解寫的很明確了,就不在囉嗦了。關於webpack.config.js中的webpack方法配置以下。

  

  執行 "npm run dev-project1"命令,啓動工程,瀏覽器中輸入「http://localhost:8000/apps/project1」,效果以下。

  

6、生產環境

  發佈到生產環境上的程序是穩定的,不容許開發人員直接操做。爲了提高服務訪問的效率,前端工程放到了要tomcat工程下。tomcat項目下的代碼仍是咱們開發人員所看到的的代碼?不是了已經!!!最後我要說的命令就是 "build-project1", 以下所示。

set NODE_ENV=prod&&webpack --display-error-details --progress --colors -p --config config.project1.js

  這個命令中設置了環境變量 NODE_ENV=prod,根據這個變量的配置,會有不一樣的 服務端產出路徑 的配置。例如, config.project1.js中的示例代碼,以下。

//服務端產出路徑
if(process.env.NODE_ENV==='prod') {//生產環境
  options.publicPath = '/project1-front';
}else if(process.env.NODE_ENV==='test') {//測試環境
  //options.publicPath = '/icop-sampleapp-frontend';
}else{//本地開發環境
}

  那麼本地開發環境中對應的這個路徑是啥呢?webpack.config.js中的webpack方法中有這樣的配置,以下。

output: {
    path: options.path || path.join(rootPath, 'apps/'+key)//編譯後的輸出路徑
    , filename: options.filename || '/build/bundle.js'
    , publicPath: options.publicPath || '/apps/'+key//服務端的路徑
    , chunkFilename: "/build/[name]_[hash].chunk.js"
},

  也就是默認的publicPath是'/apps/project1'(由於傳遞的key值是 'project1')。執行命令"npm run build-project1", 會在project1目錄下生成 build文件夾,內如以下。

  

  這些打包出來的文件是 tomcat中對應項目須要的。而且前端項目 project1中index.html也引入了其中的一些文件,以下所示。

  

  如何把咱們前端項目 發佈到 tomcat上呢?很簡單的,新建一個web工程,工程的名稱要注意, 要和 生產環境對應的 服務器產出路徑一致,即 "project1-front"。web.xml作一下簡單配置,以下。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>project1-front</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

  接下把前端項目功能節點project1目錄下面的文件(不包含"src"目錄)copy到剛剛新建的web項目(project1-front)中的 WebContent 目錄下,以下所示。

  

  最後啓動web工程,瀏覽器中輸入"http://localhost:8029/project1-front",效果以下。

  

 7、webpack的CommonsChunkPlugin提取公共代碼,以及懶加載方式

  相關連接:http://webpack.github.io/docs/long-term-caching.html

  在webpack.config.js中webpack方法對應的配置以下所示。

  

  路由各個功能節點的引入方式,變成以下。

  

 

  比較一下,使用懶加載方式(project1)和不是懶加載方式(project2)build以後產生文件的差別。

  apps/project1/build目錄

  

  apps/project2/build目錄

  

  很明顯,懶加載方式能夠更好的解決性能問題,加快頁面加載速度。不一樣的功能模塊加載對應的chunk文件就能夠了。

8、nodejs中exports與module.exports的區別

  http://cnodejs.org/topic/5231a630101e574521e45ef8

  http://zihua.li/2012/03/use-module-exports-or-exports-in-node/

  http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

  http://www.cnblogs.com/pigtail/archive/2013/01/14/2859555.html

9、教訓

  開始用懶加載模式的時候,啓動工程,出現以下錯誤。

vendor.dll.js:1 Uncaught Invariant Violation: Minified React error #130; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=130&args[]=object&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

  找了好長時間的緣由,居然是有一個js文件的導出方式的問題,以下。

  

  然而懶加載的時候,使用的require。這也就是爲啥 import能夠,require不行的緣由了。坑了我很久啊!

  

  試了一下,要改爲 module.exports = ModuleRouters。這樣纔不會報錯。

10、項目下載地址

  https://github.com/hjzgg/webpack-react-redux-next

11、項目演示地址

  http://study.hujunzheng.cn:8000/DEMO_FRONT

相關文章
相關標籤/搜索