create-react-app 是业界最优秀的 React 应用开发工具之一,本文会带你从0到1建立基于create-react-app的工程。javascript
npx create-react-app my-app
cd my-app
npm start
复制代码
注意使用npx要你的npm要在 5.2.0以上,npx会帮你执行依赖包里的二进制文件,这里很少作叙述; 构建完成后css
进入你的项目后你会看到以下的文件目录html
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ └── favicon.ico
│ └── index.html
│ └── manifest.json
└── src
└── App.css
└── App.js
└── App.test.js
└── index.css
└── index.js
└── logo.svg
└── registerServiceWorker.js
复制代码
有意思的事情来了,你并无看到关于webpack的配置, 因而去package.json里查看一下script,以下:java
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
复制代码
命令都是经过react-scripts发起的,猜想是 react-scripts 是一个包,去node_modules里找一下,果真如此;node
react-scripts 是一个生成的项目所须要的开发依赖,目录以下:react
react-scripts
├── README.md
├── node_modules
├── package.json
├── bin
│ └──react-scripts.js
├── config
│ └── jest
│ └── env.js
│ └── paths.js
│ └──polyfills.js
│ └──webpack.config.dev.js
│ └──webpack.config.prod.js
│ └──webpackDevServer.config.js
└── scripts
└── utils
└──createJestConfig.js
└── build.js
└── eject.js
└── init.js
└── start.js
└── test.js
└── template
复制代码
执行webpack
npm run eject
复制代码
你会看到 react-scripts 的配置放到了你的项目的根目录下,同时查看package.json也有相应的变化,这里create-react-app已经帮你把须要的安装依赖添加的node_modules里;git
既然要实现可高度自定义配置,就把babel编译所须要的插件也都单独放到咱们本身的项目里吧; 根目录下新建presets.js ,查看babel-preset-react-app包下的文件,把index文件内容放入presets.js,并把babel-preset-react-app包下的项目依赖放入本身的项目下 修改config/jest/babelTransform.jsgithub
module.exports = babelJest.createTransformer({
presets: [require.resolve('../presets.js')],
babelrc: false,
});
复制代码
至此,若是你须要再添加什么插件就能够在presets.js里自行引入了,例如我但愿在项目里可使用es7的装饰器,就引入了 babel-plugin-transform-decorators-legacyweb
require.resolve('babel-plugin-transform-decorators-legacy')
复制代码
并在.babelrc里配置
{
"presets": [
"es2015",
"react",
"stage-0",
"react-native-stage-0/decorator-support"
],
"plugins": [
"transform-decorators-legacy",
"transform-runtime", ["import",{"libraryName":"antd","style":true}]
]
}
复制代码
一样的,若是你须要引入某个polyfills,在config/polyfills.js里添加就ok; 好比我添加了
require("babel-polyfill");
require("babel-register");
复制代码
执行 npm start 试一下 以上咱们就完成了把配置文件从react-scripts移到咱们本身的项目里,别着急,这只是第一步;
下面咱们开始咱们的自定义配置
根据须要配置,这里我添加了Sass; 首先,咱们须要先安装Sass
npm install --save node-sass-chokidar
复制代码
修改package.json 文件
"scripts": {
+ "build-css": "node-sass-chokidar src/ -o src/",
+ "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom",
"eject": "node scripts/eject.js"
}
复制代码
咱们须要在启动的时候同时执行watch-css和start.js,因此须要安装一个包npm-run-all
npm install --save npm-run-all
复制代码
修改package.json文件
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
- "start": "node scripts/start.js",
- "build": "node scripts/build.js",
+ "start-js": "node scripts/start.js",
+ "start": "npm-run-all -p watch-css start-js",
+ "build-js": "node scripts/build.js",
+ "build": "npm-run-all build-css build-js",
复制代码
这个时候你能够在项目里使用scss文件写样式,例如咱们把App.css 更名为App.scss,并使用scss语法编写样式,执行命令
npm start
复制代码
你会看到会自动再生成一个编译好的和scss文件同名的css文件;
你没必要作任何设置,create-react-app的原有的配置已经帮你作了; 这个设置会压缩你的CSS,并经过Autoprefixer自动将供应商前缀添加到它中,你没必要担忧了各个浏览器的兼容问题了。
首先安装 react-router-dom
npm install --save react-router-dom
复制代码
这里给出一个简单的react-router-dom例子
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const BasicExample = () => (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);
const Home = () => (
<div>
<h2>Home</h2>
</div>
);
const About = () => (
<div>
<h2>About</h2>
</div>
);
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>Rendering with React</Link>
</li>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>Props v. State</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
export default BasicExample;
复制代码
具体关于react-router-dom的用法请参考官网
webpack配置变更:
// 修改webpack配置
{
loader: require.resolve('postcss-loader'),
options: {
config: {
path: 'postcss.config.js' // 这个得在项目根目录建立此文件
},
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss'
// plugins: () => [
// require('postcss-flexbugs-fixes'),
// autoprefixer({
// browsers: [
// '>1%',
// 'last 4 versions',
// 'Firefox ESR',
// 'not ie < 9', // React doesn't support IE8 anyway // ], // flexbox: 'no-2009', // }), // ], }, }, 复制代码
根目录新建 postcss.config.js
module.exports = {
"plugins": [
require('postcss-flexbugs-fixes'),
require("autoprefixer")({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), require("postcss-aspect-ratio-mini"), require("postcss-write-svg")({ utf8: false }), require("postcss-cssnext")({ features: { autoprefixer: false, } }), require("postcss-px-to-viewport")({ viewportWidth: 750, viewportHeight: 1334, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: ['.ignore', '.hairlines'], minPixelValue: 1, mediaQuery: false }), require("postcss-viewport-units"), require("cssnano")({ preset: "advanced", autoprefixer: false, "postcss-zindex": false }) ] } 复制代码
上面的配置中,postcss-px-to-viewport能够然咱们像原来同样去写px
viewportWidth和viewportHeight的配置根据大家家ui给出的设计稿来定就行了。
postcss-write-svg插件主要经过使用border-image和background来作1px的相关处理。好比 咱们先写一个1像素边框
@svg 1px-border {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
复制代码
在须要的时候就能够这样使用
.example {
border: 1px solid transparent;
border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}
复制代码
固然还有background-image的实现方式,具体参考postcss-write-svg
安装插件
npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg postcss-cssnext postcss-viewport-units cssnano cssnano-preset-advanced --D
复制代码
package.json文件中:
"dependencies": {
"cssnano": "^3.10.0",
"postcss-aspect-ratio-mini": "0.0.2",
"postcss-cssnext": "^3.1.0",
"postcss-px-to-viewport": "0.0.3",
"postcss-viewport-units": "^0.1.3",
"postcss-write-svg": "^3.0.1",
},
复制代码
注意:autoprefixery一次就够了 在cssnano和postcss-cssnext把默认配置改成false,不然会影响性能
接下来,修改 public/index.html 主要有三个地方
<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover">
复制代码
<script src="//g.alicdn.com/fdilab/lib3rd/viewport-units-buggyfill/0.6.2/??viewport-units-buggyfill.hacks.min.js,viewport-units-buggyfill.min.js"></script>
复制代码
<script>
window.onload = function () {
window.viewportUnitsBuggyfill.init({
hacks: window.viewportUnitsBuggyfillHacks
});
var winDPI = window.devicePixelRatio;
var uAgent = window.navigator.userAgent;
var screenHeight = window.screen.height;
var screenWidth = window.screen.width;
var winWidth = window.innerWidth;
var winHeight = window.innerHeight;
console.log(
"Windows DPI:" + winDPI +
";\ruAgent:" + uAgent +
";\rScreen Width:" + screenWidth +
";\rScreen Height:" + screenHeight +
";\rWindow Width:" + winWidth +
";\rWindow Height:" + winHeight
)
}
</script>
复制代码
另外,还能够经过媒体查询对iphoneX可能出现的兼容问题进行hack, 代码以下:
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
/* iPhone X 独有样式写在这里*/
}
复制代码
若是你的项目须要引入antd请参考这里
安装react-app-rewired用来重写配置
npm i react-app-rewired --dev
复制代码
使用 babel-plugin-import实现按需加载
npm i babel-plugin-import --dev
复制代码
使用react-app-rewire-less,经过 less 变量覆盖功能自定义主题
npm i react-app-rewire-less --dev
复制代码
antd 官网上须要咱们配置package.json中的scripts
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
}
复制代码
可是咱们已经再也不使用react-scripts了,而是用了本身的配置,因此咱们去看一下react-app-rewired作了什么 // 这里我读了react-app-rewired的代码作了一些处理,至于使用,你只须要在项目根目录建立一个 config-overrides.js 用于修改默认配置。
以下
const { injectBabelPlugin } = require('react-app-rewired');
const rewireLess = require('react-app-rewire-less');
module.exports = function override(config, env) {
config = injectBabelPlugin(['import', { libraryName: 'antd', style: 'css' }], config);
config = injectBabelPlugin(['import', { libraryName: 'antd', style: true }], config);
config = rewireLess.withLoaderOptions({
modifyVars: { "@primary-color": "#1DA57A" },
})(config, env);
return config;
};
复制代码
在script的start.js和build.js里添加:
// 自定义配置
const overrides = require('../config-overrides');
const webpackConfig = require('../config/webpack.config.dev');
require.cache[require.resolve('../config/webpackDevServer.config.js')].exports =
overrides(webpackConfig, process.env.NODE_ENV);
复制代码
具体实例参考个人github,欢迎交流指正 react-cli