1) 下载nodejs安装包:http://nodejs.org/en/download/javascript
nodejs安装时会同时安装npm
命令行输入如下命令,查看npm和node版本:
npm -v
node -v
若未安装成功可检查环境变量是否安装时自动设置成功css
命令行输入:npm install -g create-react-app
html
create-react-app:能够用来快速建立react项目
-g:全局安装create-react-app脚手架工具,这个步骤只须要执行一次
命令行输入: npm install express-generator -g
前端
express-generator:能够用来快速建立express应用
-g:全局安装express-generator脚手架工具,这个步骤只须要执行一次
前端框架:react
服务端:基于node的express框架
二者结合快速建立web项目。因为服务端代码须要部署到服务器,为了方便操做,先建立react项目,而后在react项目目录下建立express项目,将react的打包目录设置为express项目下的public文件。java
create-react-app myapp
cd myapp express-generator --view=ejs server
添加模版引擎:--view=ejs,此处选择ejs做为模版引擎。还能够选择pub、jade等其它模版引擎
使用create-react-app建立的项目,已经把webpack、babel等配置都封装到依赖项目react-script中,所以在目录外层没法看到webpack等配置文件。node
1)自动生成的项目目录介绍react
B. public:公共目录,该目录下的文件都不会被webpack进行加载、解析和打包;经过npm run build进行打包时该目录下的全部文件将会直接被复制到build目录下;webpack
C. src: 是源码目录,该目录下除了index.js App.test.js registerServiceWorker.js 文件具备必定意义其他文件都是演示使用可直接删除。git
首先说明:经过npm run 执行下面命令其实是运行 node_modules/react-srcipt/script下对应的脚本文件;github
create-react-app默认生成的是单入口单出口生产环境,统一经过react-script进行管理,没法知足复杂的多入口项目的须要,所以须要对项目进行配置,使其知足实际项目须要。可经过npm run eject来暴露全部内建配置,以方便咱们对项目的配置进行修改。
进入myapp根目录,执行如下命令:npm run eject
。暴露全部内建配置,项目下会新增或对部分配置文件进行修改。
根目录下新增config(配置文件)和script(脚本文件)目录。
注意:此操做不可逆,一旦执行没法回退;
修改配置的其它方法:也可考虑采用react-app-rewired插件来实现配置覆盖。
项目默认只有index.js(src目录下)这一个入口文件。
以在src目录下新增入口文件admin.js为例。
需修改config中的配置文件来:
//这里我已经写成对象格式了 //有多少个页面就添加多少个key:value //这里我已经添加了一个admin //数组中的paths.appSrc+'/admin.js'就是这个html页面的入口文件 entry: { index:[ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appIndexJs, ], admin:[ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appSrc + '/admin.js', ] }
//多少个页面就new 多少个 HtmlWebpackPlugin //而且在每个里面的chunks都须要和上面的entry中的key匹配 //例如上面entry中有index和admin这两个。 //这里的chunks也须要是index和admin new HtmlWebpackPlugin({ inject: true, chunks:["index"], template: paths.appHtml, }), new HtmlWebpackPlugin({ inject: true, chunks:["admin"], template:paths.appHtml, filename:'admin.html' }),
//因为原配置入口文件只有一个,所以output中的filename是写死的, //增长多入口以后,输出文件名被写死,对应生成了多个boundle.js, //后面生成的会覆盖前面生成的文件,因此须要制定输出的文件名不能写死 output: { path:paths.appBuild, pathinfo: true, filename: 'static/js/[name].bundle.js', chunkFilename: 'static/js/[name].chunk.js', publicPath: publicPath, devtoolModuleFilenameTemplate: info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'), },
//这里的paths.appIndexJs和paths.appSrc+'/admin.js'是入口文件 entry:{ index:[ require.resolve('./polyfills'), paths.appIndexJs ], admin:[ require.resolve('./polyfills'), paths.appSrc+'/admin.js' ] }
//和开发环境下同样,多少个html就new多少个 HtmllWebpackPlugin,每一个都须要指定chunks,而且指定filename,在minify中配置是否压缩js、css等,这是生产环境下的配置 new HtmlWebpackPlugin({ inject: true, chunks:["index"], template: paths.appHtml, minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, }), new HtmlWebpackPlugin({ inject: true, chunks:["admin"], template: paths.appHtml, filename:'admin.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, }),
//这里的rewrites:[ {from: /^\/admin.html/, to: '/build/admin.html' }] 数组里面是一个个对象, //对象中前面的值是在开发时候访问的路径,例如 npm run start以后会监听 localhost:3000 , //此时在后面加上 /admin.html就会访问admin.html中的内容,默认是访问index.html; //数组中的第二个值是生产环境下的文件的路径。 //若是有不少页面,就在rewrites中添加更多对象 historyApiFallback: { disableDotRule: true, rewrites: [ { from: /^\/admin.html/, to: '/build/admin.html' }, ] },
生产环境:本文中的项目,因为打包后的代码会放在server目录下的public文件夹下,也就是打包后的代码和server在同域下,不存在跨域问题。
开发环境:开发时,前端react项目和后端express项目运行时端口端口不一样,存在跨域问题。
开发环境跨域问题解决办法:在package.json中加入:"proxy":http://localhost:5000 //后端所在域
。
若是须要后端存在多个域:
//package.json中加入 "proxy": { "/api1": { "target": "http://api1.xxxx.com", "changeOrigin":true }, "/api2":{ "target":"http://api2.xxxx.com", "changeOrigin":true } }
当页面嵌套过深时,import Apis from '../../common/apis',可经过webpack配置来简化路径。
//修改webpack.config.dev与webpack.config.prod两个文件,加入相同配置 //增长方法 function resolve(dir) { return path.join(__dirname, '..', dir) } //修改 alias配置 alias: { 'react-native': 'react-native-web', //加入配置 '@src': resolve('src') }
添加上述配置后,引入文件方式:import Apis from '@src/common/apis'
缺点:此方法能简化引用方法,但没法经过快捷键进入该引用文件。
//修改webpack.prod.conf.js文件,增长以下内容 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] } //修改package.json文件,在scripts中增长以下命令 “analyz”: “NODE_ENV=production npm_config_report=true npm run build”
npm run build
或npm run analyz
,浏览器会自动打开127.0.0.1:8888,以下页面,可查看打包后文件分布,以及打包文件大小。安装方法: npm install uglifyjs-webpack-plugin --save-dev
在webpack.config.prod.js文件中添加 const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = { plugins: [ new UglifyJSPlugin(), ] }
//修改webpack.config.prod.js文件: //注释devtool:shouldUseSourceMap? 'source-map':false devtool:false,//增长
//修改webpack.config.dev.js文件: module:{ rules:[{ use:[ //添加在最前面 'cache-loader', ] }] }
在其它加载程序加载以前添加以将结果缓存在磁盘上
修改webpack.config.prod.js文件
//修改entry文件, entry: //这里的paths.appIndexJs和paths.appSrc+'/admin.js'依然是每一个html的入口文件 { index:[ require.resolve('./polyfills'), paths.appIndexJs, ], admin:[ require.resolve('./polyfills'), paths.appSrc+'/admin.js' ], //增长vendor vendor:['react','react-dom'] }, //修改plugin plugin:{ //新增如下代码 new webpack.optimize.CommonsChunkPlugin({ name: ["vendor"], // filename:'static/js/vendor.[chunkhash:8].js', // minChunks: 3 //三方库在逻辑代码中被调用两次(数字能够自定义), 将公共的代码提取出来 }), /* 防止 vendor hash 变化 */ // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }), } //修改plugins中的HtmlWebpackPlugin,在chunks中添加须要引入的公共包, //其中公共包需放在后面,使其在加入html页面时能在其它js文件前面 new HtmlWebpackPlugin({ inject: true, chunks:["index","vendor"], template: paths.appHtml, minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, },}),new HtmlWebpackPlugin({ inject: true, chunks:["admin","vendor"], template: paths.appHtml, filename:'admin.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, },}),
命令行输入:npm run build
,出现如下文件夹,其中admin.html和index.html分别是不一样的入口。
可在path.js文件中修改打包后资源文件路径,例如修改path.js文件中getServedPath方法中的‘/’,改成‘/build’,则打包后资源文件的路径会加上build,修改前资源文件路径中是没有build的。
本文中react+express的项目,无需修改资源文件根路径,由于express会配置资源文件所在目录为。
express框架中启动项目后,文件更新后须要手动重启node服务,修改才会生效。使用nodemon能够实现热启动,文件修改后自动重启使修改生效。
在server根目录(express项目根目录)下运行如下命令,安装nodemon:npm --save-dev install nodemon
//修改server(express项目根目录)目录下的package.json文件,将node改成nodemon //将"start":"node ./bin/www"改成: "start":"nodemon ./bin/www"
为了方便,将react打包目录修改成server目录下public目录,能够避免每次打包后都须要将build目录下的文件在复制到server目录下。
//修改path.js文件,module.exports中的appBuild变量 //将appBuild: resolveApp('build'),改成 appBuild: resolveApp('server/public'),
在webstorm中,会自动出现根目录下package.json中的scripts下的npm命令,为了方便启动server,可在react 根目录下的package.json文件中增长server的启动项。
"scripts": { "start": "node scripts/start.js", "server-start": "cd server && npm run start",//增长server启动命令 "build": "node scripts/build.js", "test": "node scripts/test.js" },
浏览器扩展工具中搜索此插件并安装,能够查看到react组件结构
chrome引入了source-map文件,能够查看打包前代码。惟一要作的就是配置webpack自动生成source-map文件,这也很简单,在webpack.config.js中增长一行配置便可(须要从新启动webpack-dev-server使配置生效),create-react-app已作此配置,所以不须要再修改。
Create-react-app已安装Eslint,可对eslint进行自定义配置规则。
开发目录主要是src目录,所以须要修改的目录主要是src目录。
|——src |————|common //公共组件目录,如http.js、cookie.js等 |————|components //基础组件、业务组件、业务代码抽象出的一些基础类,例如每一个页面能够在此目录下创建一个文件存放相关组件。 |————|layouts //布局相关组件及其样式文件,如header.js、footer.js、menu.js等 |————|styles //公共样式文件 |————|static //公共的静态资源文件,如公共的图片资源文件等 |————|views //页面入口文件,可与comonents中的页面组件对应
若是使用了router和redux可在src下增长目录:
|——server // express项目根目录 |————|bin |——————|www //服务器相关配置文件 |————|controllers //控制器层,处理前端请求 |————|models //数据库操做相关文件 |————|node_modules //npm包安装目录 |————|public //react打包目录,存放全部的html,js/css/图片等资源文件 |————|routes // 路由文件目录 |——————|api.js //api请求路由文件 |——————|pages.js // 页面请求路由文件 |————|utils // 公共文件目录 |——————|config.js //各类常量或公共方法 |——————|db.js // 数据库访问方法封装 |——————|http.js //http请求方法封装 |————|views // express框架自带,因为打包后的文件全放在public目录下,所以这个文件可不用了 |————|app.js //入口文件 |————|package.json |————|package-lock.json