修改 package.json
"dependencies": { "babel-loader": "^5.0.0", "css-loader": "^0.12.0", "postcss-loader": "^0.4.2", "react": "^0.13.2", "style-loader": "^0.12.1", "cssnext": "^1.4.0", "suitcss": "latest", "suitcss-base": "latest", "suitcss-components-arrange": "latest", "suitcss-components-button": "latest", "suitcss-components-flex-embed": "latest", "suitcss-components-grid": "latest", "suitcss-utils-align": "latest", "suitcss-utils-display": "latest", "suitcss-utils-layout": "latest", "suitcss-utils-link": "latest", "suitcss-utils-offset": "latest", "suitcss-utils-position": "latest", "suitcss-utils-size": "latest", "suitcss-utils-text": "latest" }
安装新添加的 loaders
$ npm install
修改 webpack.config.js 来使用 postcss
const cssnext = require('cssnext'); module.exports = { entry: './src/main.js', output: { path: './leancloud/public', filename: 'bundle.js' }, resolve: { extensions: ['', '.jsx', '.js', '.css'], modulesDirectories: ["src", "node_modules"] }, module: { loaders: [ { test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/ }, { test: /\.css$/, loader: 'style!css!postcss' } ] }, postcss: [ cssnext({ import: { path: ['node_modules', 'src/css'] } }) ] };
添加 src/css/base.css
@import "suitcss-base"; @import "variables";
添加 src/css/components/footer.css
.tl-Footer { font-style: italic; }
添加 src/css/components/container.css
.tl-Container { background: var(--color-red); } @import "variables";
添加 src/css/variables.css
/** * Breakpoints */ @custom-media --sm-viewport (min-width:320px); @custom-media --md-viewport (min-width:640px); @custom-media --lg-viewport (min-width:960px); /** * Colors */ :root { --color-twitter-blue: #55acee; --color-white: #fff; /* Primary grays */ --color-charcoal: #292f33; --color-dark-gray: #66757f; --color-medium-gray: #8899a6; --color-gray: #ccd6dd; --color-border-gray: #e1e8ed; --color-faint-gray: #f5f8fa; /* Primary blues */ --color-dark-blue: #226699; --color-deep-blue: #3b88c3; --color-light-blue: #88c9f9; /* Secondary colors */ --color-orange: #ffac33; --color-green: #77b255; --color-purple: #9266cc; --color-red: #dd2e44; --color-yellow: #ffcc4d; /* Secondary color variants */ --color-dark-orange: #f4900c; --color-dark-green: #3e721d; --color-dark-purple: #553788; --color-dark-red: #a0041e; --color-deep-green: #5c913b; --color-deep-purple: #744eaa; --color-deep-red: #be1931; --color-light-yellow: #ffd983; --color-light-green: #a6d388; --color-light-purple: #aa8dd8; --color-light-red: #ea596e; --color-faded-yellow: #ffe8b6; --color-faded-green: #c6e5b3; --color-faded-blue: #bbddf5; --color-faded-purple: #cbb7ea; --color-faded-red: #f4abba; } /** * Fonts */ :root { --font-size: 16px; --font-family: sans-serif; --line-height: 1.4; } /** * Spacing */ :root { --space-small-px: 10px; --space-medium-px: 15px; --space-large-px: 20px; }
这里都是用的 CSS4 的语法,主要用来改 SUIT CSS 的一些参数,和我们会用到的各个组件的参数
把 src/components 改为 src/js/components
新建 src/js/components/Container.js
const React = require("react"); const Header = require("js/components/Header"); const Footer = require("js/components/Footer"); require("css/components/container"); require("suitcss-utils-layout"); const Container = React.createClass({ render () { return ( <div className="tl-Container u-cf"> <Header /> <Footer /> </div> ); } }); module.exports = Container;
现在和 commonJS 一样,每个 Component 都需要 require 对应的 css 文件。比如这里用了 tl-Container 和 u-cf 这两个
class,就需要分别 require 他们对应的文件。
新建 src/js/components/Header.js
const React = require("react"); require("css/components/header"); const Header = React.createClass({ render () { return ( <div> <div className="tl-Header"> Header </div> </div> ); } }); module.exports = Header;
新建 src/js/components/Footer.js
const React = require("react"); require("css/components/footer"); const Footer = React.createClass({ render () { return ( <div className="footer"> Footer </div> ); } }); module.exports = Footer;
修改 src/main.js
const React = require("react"); const Container = require("js/components/Container"); require("css/base"); React.render(<Container />, document.getElementById("main"));
再运行 webpack 编译后,在 localhost 里面就能看到新的带 css 的页面了
如果你注意,你会发现 css 会自动加载到 header 里面,而不是单独的 css 文件。这就是 webpack 的一个独特的地方,他只会加载当前页面需要的 css 文件,如果你的 App 有很多页面,比如 admin 的话,在页面 A 就不会加载页面 B 的 style。
当然这么做也会有一些弊端,比如如果 css 文件很大的话,那么在页面加载过程中会出现几秒没有美化的页面,直到整个 bundle.js 加载成功才会出现美化。
单一 css 文件
要解决这个问题,可以使用一个 webpack 的 plugin
$ npm install extract-text-webpack-plugin --save
修改 webpack.config.js
const webpack = require('webpack'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const cssnext = require('cssnext'); const definePlugin = new webpack.DefinePlugin({ __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'false')) }); module.exports = { entry: './src/main.js', output: { path: './leancloud/public', filename: 'bundle.js' }, resolve: { extensions: ['', '.jsx', '.js', '.css'], modulesDirectories: ["src", "node_modules"] }, module: { loaders: [ { test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/ }, { test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css!postcss') } ] }, postcss: [ cssnext({ import: { path: ['node_modules', 'src/css'] } }) ], plugins: [ definePlugin, new ExtractTextPlugin("bundle.css") ] };
再运行 webpack,你会发现 leancloud/public 里面,除了 bundle.js
之外,还多出了一个 bundle.css
注意这里我还加了段 definePlugin,有什么用呢?如果在你的源码里面加入
if (__DEV__) { console.log('Dev'); }
的话,那么这一段只会在本地运行,在 webpack -p 的时候这段代码会被自动移除掉
现在在 index.ejs 里面的 header 里加上
<link rel="stylesheet" href="bundle.css" />
刷新浏览器,你会发现一样的结果,只不过现在的 style 都在 bundle.css 里面了
部署到 production
$ webpack -p
$ cd leancloud
$ avoscloud deploy
$ avoscloud publish
现在访问 timeline.avosapps.com,能看到刚才的修改都已经上线了。
把常用的命令放到 package.json 里面
修改 package.json
"scripts": { "start": "cd leancloud && avoscloud -P 4567 && cd $OLDPWD", "watch": "BUILD_DEV=1 webpack --watch", "clean": "rm -rf leancloud/public/*", "build": "npm run clean && NODE_ENV=production webpack -p", "deploy": "cd leancloud && avoscloud deploy && cd $OLDPWD", "publish": "cd leancloud && avoscloud publish && cd $OLDPWD" },
现在用 npm run XX 就可以跑一些常用的命令,你也可以把其中一些打包起来
