利用Webpack+React(antd)+ES6+python(flask)实现代码转换
之前的几篇博客是将flask 结合 antd本地化,但是这样使得antd无法按需加载(也不支持ES6的语法),而且在写的过程中还需要把每个组件都用antd对象,这样的做法虽然是实现了antd的本地化,但是无法最大化的使用antd组件库,最好的方式就是官网上的组件代码直接拿过来用就行,今天所做的就是这个功能。
首先是借用Webpack ,它是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。
一、安装webpack1.安装webpack(项目根目录下):
$npm install webpack --save-dev
2.Webpack需要某些配置才能完成给他的工作。所以我们需要在项目根目录下创建一个webpack.config.js
的配置文件。写入以下内容:
var webpack = require('webpack'); var path = require('path'); var APP_DIR = path.resolve(__dirname, 'static/components'); var BUILD_DIR = path.resolve(__dirname, 'static/js'); var config = { entry: APP_DIR + '/index.jsx', output: { path: BUILD_DIR, filename: 'bundle.js' } }; module.exports = config;
Webpack的配置最少需要两项,一个是入口属性,一个是输出属性。APP_DIR
指向React项目的代码所在目录,BUILD_DIR
指向打包后文件的输出目录。
就如同配置项名称所表达的一样。entry是打包所需要的入口文件。如果你对静态语言,比如c/c++之类的熟悉的话。这个入口文件就是c/c++包含main方法的文件。Webpack支持多个入口文件。这里目录static/components里的index.jsx文件就是整个应用的入口文件。
output指明webpack在打包完成后需要做什么。这里,使用static/js目录存放打包后生成的文件bundle.js。
在static/components目录下创建文件index.jsx。并添加如下代码:
console.log('Hello World!');
在terminal里输入下面的命令。
$ ./node_modules/.bin/webpack -d
命令会调用webpack,生成开发环境下的bundle.js文件以及关联的map文件bundle.js.map。这两个文件都在配置文件制定的目录static/js下。
但是目前只看到了编译之后的js文件,不够直观。在目录templates下创建一个index.html文件。这样js文件是否加载成功都能看到了。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>webpack</title> </head> <body> <div id="ES6Box"></div> <script src="/static/js/bundle.js"> </script> </body> </html>
如果成功将会看到“Hello World!”。
二、使用Babel-Loader
babel-loader使得EM2015以及React语法通过webpack翻译以后生成浏览器所识别的代码:
1.使用npm安装babel-loader。
$ npm install babel-loader babel-preset-es2015 babel-preset-react --save-dev
babel-preset-es2015和babel-preset-react是babel-loader
使用的插件。专门用来翻译JSX和ES2015语法。安装之后还需要配置一下才能使用。
项目根目录下创建一个.babelrc的文件,并添加一下内容。
{ "presets": ["es2015", "react"] }
2.告诉webpack使用babel-loader
来打包文件。
打开webpack.config.js并添加如下内容。
var webpack = require('webpack'); var path = require('path'); var APP_DIR = path.resolve(__dirname, 'static/components'); var BUILD_DIR = path.resolve(__dirname, 'static/js'); var config = { entry: {
index1: APP_DIR + '/index.jsx',
react1: APP_DIR + '/react.jsx',
//多个文件可在后面追加。。。
},
output: {
path: BUILD_DIR,
filename: '[name].js' //所有编译的文件都在static/js,文件名为entry设定的name,上面两个文件编译完以后为index1.js\react1.js。
}, module: { rules: [ { test: /\.jsx$/, use: [ 'babel-loader', ], include: [ // path.resolve(__dirname, "app") APP_DIR ], }], } }; module.exports = config;
loaders
属性对应的值是一个数组。不过我们只是用babel-loader
。每一个加载器都需要通过test
属性指定可以处理的文件的后缀。babel-loader
用来处理.js和.jsx文件。include
属性指定处理哪个目录下的文件。loader
属性就是加载器的名称。npm install react react-dom --save
import React from 'react'; import {render} from 'react-dom'; class App extends React.Component { render() { return <p> Hello World! </p> } } render(<App />, document.getElementById('app'));
执行命令:
$ ./node_modules/.bin/webpack -d
成功以后即可看到Hello World!。
4.webpack监视文件变化,实时更新
$ ./node_modules/.bin/webpack -d --watch
ps:如果在实际项目时,运行终端时候启动服务以及占去一个终端,这个时候我们可以另起一个终端来监视文件变化,这样两边互不干扰。
三、使用antd组建
在从上面步骤做下来已经实现了浏览器支持react和ES6的语法了,下面是引入antd组件库》
1.安装:
$ npm install antd --save
这个时候你会发现pakage.json中你安装的所有东西都在里面。
{ "name": "webpack-example", "version": "1.0.0", "description": "A simple webpack example.", "main": "bundle.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "webpack" ], "author": "jiang", "license": "MIT", "devDependencies": { "babel-loader": "^6.4.1", "babel-plugin-import": "^1.1.1", "babel-preset-es2015": "^6.24.0", "babel-preset-react": "^6.23.0", "babel-preset-stage-1": "^6.22.0", "webpack": "^2.3.2" }, "dependencies": { "antd": "^2.8.3", "react": "^15.4.2", "react-dom": "^15.4.2" } }
2.引用antd
将index.jsx中的内容换为antd官网中的任意一个组件代码,此处以表格为例:
import React from 'react'; import ReactDOM from 'react-dom'; import Form from 'antd/lib/form'; import Icon from 'antd/lib/icon'; import Button from 'antd/lib/button'; import Input from 'antd/lib/input'; const FormItem = Form.Item; function hasErrors(fieldsError) { return Object.keys(fieldsError).some(field => fieldsError[field]); } class HorizontalLoginForm extends React.Component { componentDidMount() { // To disabled submit button at the beginning. this.props.form.validateFields(); } handleSubmit = (e) => { e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { console.log('Received values of form: ', values); } }); } render() { const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form; // Only show error after a field is touched. const userNameError = isFieldTouched('userName') && getFieldError('userName'); const passwordError = isFieldTouched('password') && getFieldError('password'); return ( <Form layout="inline" onSubmit={this.handleSubmit} style={{marginTop:50,marginLeft:50}}> <FormItem validateStatus={userNameError ? 'error' : ''} help={userNameError || ''} > {getFieldDecorator('userName', { rules: [{ required: true, message: 'Please input your username!' }], })( <Input prefix={<Icon type="user" style={{ fontSize: 13 }} />} placeholder="Username" /> )} </FormItem> <FormItem validateStatus={passwordError ? 'error' : ''} help={passwordError || ''} > {getFieldDecorator('password', { rules: [{ required: true, message: 'Please input your Password!' }], })( <Input prefix={<Icon type="lock" style={{ fontSize: 13 }} />} type="password" placeholder="Password" /> )} </FormItem> <FormItem> <Button type="primary" htmlType="submit" disabled={hasErrors(getFieldsError())} > Log in </Button> </FormItem> </Form> ); } } const WrappedHorizontalLoginForm = Form.create()(HorizontalLoginForm); ReactDOM.render(<WrappedHorizontalLoginForm />,document.getElementById('ES6Box'));
在引进的过程中需要注意几点,注意上面的红色代码:
import React from 'react'; import ReactDOM from 'react-dom'; import Form from 'antd/lib/form'; import Icon from 'antd/lib/icon'; import Button from 'antd/lib/button'; import Input from 'antd/lib/input';
第一、二两行是引入React和ReactDOM,否则浏览器会报ReactDOM、React没有定义的错误。
后面则是antd的按需加载,也可以借用插件 babel-plugin-import
完成上面操作以后如果出现语法错误,不支持ES6的箭头函数或者其他语法
需要下载bable转码器:
$ npm install --save-dev babel-preset-stage-1
在.babelrc文件中添加规则:
{ "presets": [ "latest", "react", "stage-2" ], "plugins": [] }
这个时候刷新页面会发现没有css样式:
别着急这个时候就需要加入antd的css,需要在webpack中添加css-loader/stylr-loader,方法很简单:
1.安装css-loader style-loader:
$npm install css-loader style-loader
2.在配置文件中加入依赖,package.json中添加安装的css-loader style-loader,注意版本一定要相同:
{ "name": "webpack-example", "version": "1.0.0", "description": "A simple webpack example.", "main": "bundle.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "webpack" ], "author": "jiang", "license": "MIT", "devDependencies": { "babel-loader": "^6.4.1", "babel-plugin-import": "^1.1.1", "babel-preset-es2015": "^6.24.0", "babel-preset-react": "^6.23.0", "babel-preset-stage-1": "^6.22.0", "webpack": "^2.3.2" }, "dependencies": { "antd": "^2.8.3", "react": "^15.4.2", "react-dom": "^15.4.2", "css-loader": "^0.27.3", "style-loader": "^0.16.1" } }
添加以后需要重新执行命令:npm install 更新一下。
3.在webpack.config.js中添加进来:
var webpack = require('webpack'); var path = require('path'); var APP_DIR = path.resolve(__dirname, 'static/components'); var BUILD_DIR = path.resolve(__dirname, 'static/js'); var config = { entry: { index: APP_DIR + '/index.jsx', react: APP_DIR + '/react.jsx', }, output: { path: BUILD_DIR, filename: '[name].js' }, module: { rules: [ { test: /\.jsx$/, use: [ 'babel-loader', ], include: [ // path.resolve(__dirname, "app") APP_DIR ], }, { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ], } }; module.exports = config;
最后在index.jsx中加入css:
import 'antd/dist/antd.css';
重新执行命令./node_modules/.bin/webpack -d
就ok了:
这样就全部实现了antd真正的本地化,可以随心所遇的运用其官网上组件的代码了。
友情提示:过程虽然漫长而复杂,但是研究出来的一瞬间会让你觉得值得。。。
借鉴:
http://blog.csdn.net/future_challenger/article/details/52389812
http://webpackdoc.com/index.html