webpack+react+redux+es6开发模式---续

一、前言

  之前介绍了webpack+react+redux+es6开发模式 ,这个项目对于一个独立的功能节点来说是没有问题的。假如伴随着源源不断的需求,前段项目会涌现出更多的功能节点,需要独立部署运行。为了更好地管理这些独立的功能节点,我们需要利用webpack进行单独的打包处理,针对不同的功能节点生成不同的配置文件

二、项目结构

  1.项目demo目录图片示例

  

  2.apps目录图片示例(project1和project2分别表示两个不同的功能节点)

   

三、npm-scripts 命令

  package.json部分示

  

  接下来,会说明下每个命令的用途。

四、webpack的dll功能

  Dll是Webpack最近新加的功能, 我简单介绍一下。

  Dll就是一个纯纯的依赖库,它本身不能运行,是用来给你的app引用的。

  打包dll的时候,Webpack会将所有包含的库做一个索引,写在一个manifest文件中,而引用dll的代码(dll user)在打包的时候,只需要读取这个manifest文件,就可以了。

这么一来有几个好处:

  • Dll打包以后是独立存在的,只要其包含的库没有增减、升级,hash也不会变化,因此线上的dll代码不需要随着版本发布频繁更新。

  • App部分代码修改后,只需要编译app部分的代码,dll部分,只要包含的库没有增减、升级,就不需要重新打包。这样也大大提高了每次编译的速度。

  • 假设你有多个项目,使用了相同的一些依赖库,它们就可以共用一个dll。

  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

五、开发环境

  开发人员开发项目的时候,使用 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”,效果如下。

  

六、生产环境

  发布到生产环境上的程序是稳定的,不允许开发人员直接操作。为了提升服务访问的效率,前端工程放到了要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",效果如下。

  

 七、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文件就可以了。

八、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

九、教训

  开始用懒加载模式的时候,启动工程,出现如下错误。

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。这样才不会报错。

十、项目下载地址

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

十一、项目演示地址

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

转载于:https://www.cnblogs.com/hujunzheng/p/6294954.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ安装和使用(和Spring集成)

一、安装Rabbit MQ   Rabbit MQ 是建立在强大的Erlang OTP平台上&#xff0c;因此安装Rabbit MQ的前提是安装Erlang。通过下面两个连接下载安装3.2.3 版本&#xff1a; 下载并安装 Eralng OTP For Windows (vR16B03)运行安装 Rabbit MQ Server Windows Installer (v3.2.3)具体…

单点登录实现(spring session+redis完成session共享)

一、前言 项目中用到的SSO&#xff0c;使用开源框架cas做的。简单的了解了一下cas&#xff0c;并学习了一下 单点登录的原理&#xff0c;有兴趣的同学也可以学习一下&#xff0c;写个demo玩一玩。 二、工程结构 我模拟了 sso的客户端和sso的服务端&#xff0c; sso-core中主要是…

加密策略

一、前言 这两天研究了一下项目中的密码加密&#xff0c;可以说得上是学到了很多。下面来大致说一下。 二、常用加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中&#xff0c;是否被篡改过。 BASE64 严格地说&#xff0c;属于编码格式&#xff0c;而非加密算法 …

Spring Data JPA: 实现自定义Repository

一、前言 由于项目中的 实体&#xff08;entity&#xff09;默认都是继承一个父类&#xff08;包含一些公共的属性&#xff0c;比如创建时间&#xff0c;修改时间&#xff0c;是否删除&#xff0c;主键id&#xff09;。为了实现逻辑删除&#xff0c;一般会自己实现RepositoryFa…

js冲刺一下

js中__proto__和prototype的区别和关系 1.对象有属性__proto__,指向该对象的构造函数的原型对象。  2.方法除了有属性__proto__,还有属性prototype&#xff0c;prototype指向该方法的原型对象。 深入浅出妙用 Javascript 中 apply、call、bind ***两道面试题*** 关于js中伪数…

Jackson序列化实例

参考文章 Jackson使用ContextualSerializer在序列化时获取字段注解的属性 使用BeanSerializerModifier定制jackson的自定义序列化(null值的处理) 关于使用ContextualSerializer的补充 BeanSerializerFactory中有如下代码&#xff0c; 关于设置SerializerModifier&#xff0c;如…

cas4.2.7实现单点登录

准备前参考&#xff1a;  cas server下载地址 cas client 下载地址 安全cookie setSecure详解 Spring通过构造方法注入的四种方式 cas 学习博文 自定义登录页和登录认证 cas server端的login-webflow详细流程 CAS服务端自定义数据库认证用户 准备工作 1. cas server下载之后解…

swagger restful api form映射实体对象和body映射实体对象配置

实体Model ModelAttribute一个具有如下三个作用&#xff1a; ①绑定请求参数到命令对象&#xff1a;放在功能处理方法的入参上时&#xff0c;用于将多个请求参数绑定到一个命令对象&#xff0c;从而简化绑定流程&#xff0c;而且自动暴露为模型数据用于视图页面展示时使用&…

ssh端口转发(之kettle ssh方式连接数据库)

ssh参数解释 格式  ssh [user]host [command] 选项&#xff1a; -1&#xff1a;强制使用ssh协议版本1&#xff1b; -2&#xff1a;强制使用ssh协议版本2&#xff1b; -4&#xff1a;强制使用IPv4地址&#xff1b; -6&#xff1a;强制使用IPv6地址&#xff1b; -A&#xff1a…

ThreadLocal和InheritableThreadLocal使用

InheritableThreadLocal代码 public class InheritableThreadLocal<T> extends ThreadLocal<T> {protected T childValue(T parentValue) {return parentValue;}ThreadLocalMap getMap(Thread t) {return t.inheritableThreadLocals;}void createMap(Thread t, T f…

mybatis generator修改默认生成的sql模板

相关连接&#xff1a; mybatis-generator扩展教程系列 -- 自定义sql xml文件 git项目地址 转载于:https://www.cnblogs.com/hujunzheng/p/7110510.html

oauth简单使用

一、oauth原理参考 理解OAuth 2.0 二、本例中采用授权码模式 大致流程 &#xff08;A&#xff09;用户访问客户端&#xff0c;后者将前者导向认证服务器。  &#xff08;B&#xff09;用户选择是否给予客户端授权。  &#xff08;C&#xff09;假设用户给予授权&#xff0c…

我眼中的服务提供和服务消费

服务提供和消费脑图 服务提供和消费脑图 参见: 服务提供者, 服务消费者, 服务注册中心 服务提供者 1.服务提供者启动&#xff0c;解析xml文件中配置的服务&#xff0c;这里使用Dom4j解析。 2.将服务的一些相关信息注册到 服务注册中心。 注&#xff1a;服务相关信息&#xff1a…

shiro整合oauth

前言 如果oauth原理还不清楚的地方&#xff0c;其参考这里。 一、基本思路脑图 二、客户端shiro配置 shiro配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:util&q…

springmvc+swagger2

一、swagger2依赖 <!--swagger--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><exclusions><exclusion><artifactId>spring-aop</artifactId><groupId>org.s…

获取资源文件工具类

如果没有依赖spring&#xff0c;可以将分割线下的方法去掉 import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframe…

无状态shiro认证组件(禁用默认session)

准备内容 简单的shiro无状态认证 无状态认证拦截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.stateless.shiroSimpleWeb.realm.StatelessToken; import org.apache.shiro.web.filter.AccessControlFilter;import javax.servlet.ServletRequest;…

Spring根据包名获取包路径下的所有类

参考mybatis MapperScannerConfigurer.java 最终找到 Spring的一个类 ClassPathBeanDefinitionScanner.java 参考ClassPathBeanDefinitionScanner 和它的父类 ClassPathScanningCandidateComponentProvider&#xff0c;将一些代码进行抽取&#xff0c;得到如下工具类。 import…

idea模板注释

类文件头部的注释 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java") /** * ${DESCRIPTION} * author ${USER} hujunzheng * create ${YEAR}-${MONTH}-${DAY} ${TIME} **/ public class ${N…

redis分布式锁小试

一、场景 项目A监听mq中的其他项目的部署消息&#xff08;包括push_seq, status, environment&#xff0c;timestamp等&#xff09;&#xff0c;然后将部署消息同步到数据库中&#xff08;项目X在对应环境[environment]上部署的push_seq[项目X的版本]&#xff09;。那么问题来了…