1. ant.design能不能直接編譯成瀏覽器直接引用便可用
肯定是可以的,但是官方不建議這樣做,但如果題主真想這么做的話可以按照下面方法:
1. 下載並編譯ant-design
git clone https://github.com/ant-design/ant-design.git
cd ant-design
npm i --registry=http://registry.npm.taobao.org
npm run just-deploy
2. 使用方法
編譯完成後在dist目錄下antd.js和demo.css就是它的js和css文件,但是antd.js依賴react和react-dom,所以要引用node_moles/react/dist/react.js和node_moles/react-dom/dist/react-dom.js。(外加一些es5-shim等)
在ant-design根目錄下建立測試文件antd-test.html,內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="./dist/demo.css">
<script src="https://as.alipayobjects.com/??component/console-polyfill/0.2.2/index.js,component/es5-shim/4.1.14/es5-shim.min.js,component/es5-shim/4.1.14/es5-sham.min.js,component/html5shiv/3.7.2/html5shiv.min.js,g/component/media-match/2.0.2/media.match.min.js"></script>
<script src="./node_moles/react/dist/react.js"></script>
<script src="./node_moles/react-dom/dist/react-dom.js"></script>
<script src="./dist/antd.js"></script>
</head>
<body>
<div id="components-calendar-demo-basic"></div>
<script>
(function(){
'use strict';
function onPanelChange(value, mode) {
console.log(value, mode);
}
ReactDOM.render(React.createElement(antd.Calendar, {
onPanelChange: onPanelChange
}), document.getElementById('components-calendar-demo-basic'));})();
</script>
</body>
</html>
2. node+react後台用webpack怎麼做實時更新
每個模塊相關的 css、img、js 文件都放在一起,比較直觀,刪除模塊時也會方便許多。測試文件也同樣放在一起,哪些模塊有沒有寫測試,哪些測試應該一起隨模塊刪除,一目瞭然。
build
|-- webpack.config.js # 公共配置
|-- webpack.dev.js # 開發配置
|-- webpack.release.js # 發布配置
docs # 項目文檔
node_moles
src # 項目源碼
|-- conf # 配置文件
|-- pages # 頁面目錄
| |-- page1
| | |-- index.js # 頁面邏輯
| | |-- index.scss # 頁面樣式
| | |-- img # 頁面圖片
| | | |-- xx.png
| | |-- __tests__ # 測試文件
| | | |-- xx.js
| |-- app.html # 入口頁
| |-- app.js # 入口JS
|-- components # 組件目錄
| |-- loading
| | |-- index.js
| | |-- index.scss
| | |-- __tests__
| | | |-- xx.js
|-- js
| |-- actions
| | |-- index.js
| | |-- __tests__
| | | |-- xx.js
| |-- recers
| | |-- index.js
| | |-- __tests__
| | | |-- xx.js
| |-- xx.js
|-- css # 公共CSS目錄
| |-- common.scss
|-- img # 公共圖片目錄
| |-- xx.png
tests # 其他測試文件
package.json
READNE.md
要完成的功能
編譯 jsx、es6、scss 等資源
自動引入靜態資源到相應 html 頁面
實時編譯和刷新瀏覽器
按指定模塊化規范自動包裝模塊
自動給 css 添加瀏覽器內核前綴
按需打包合並 js、css
壓縮 js、css、html
圖片路徑處理、壓縮、CssSprite
對文件使用 hash 命名,做強緩存
語法檢查
全局替換指定字元串
本地介面模擬服務
發布到遠端機
針對以上的幾點功能,接下來將一步一步的來完成這個
boilerplate 項目, 並記錄下每一步的要點。
准備工作
1、根據前面的項目結構規劃創建項目骨架
$ make dir webpack-react-rex-es6-boilerplate
$ cd webpack-react-rex-es6-boilerplate
$ mkdir build docs src mock tests
$ touch build/webpack.config.js build/webpack.dev.js build/webpack.release.js
// 創建 package.json
$ npm init
$ ...
2、安裝最基本的幾個 npm 包
$ npm i webpack webpack-dev-server --save-dev
$ npm i react react-dom react-router rex react-rex rex-thunk --save
3、編寫示例代碼,最終代碼直接查看
boilerplate
4、根據
webpack 文檔編寫最基本的 webpack 配置,直接使用 NODE API 的方式
/* webpack.config.js */
var webpack = require('webpack');
// 輔助函數
var utils = require('./utils');
var fullPath = utils.fullPath;
var pickFiles = utils.pickFiles;
// 項目根路徑
var ROOT_PATH = fullPath('../');
// 項目源碼路徑
var SRC_PATH = ROOT_PATH + '/src';
// 產出路徑
var DIST_PATH = ROOT_PATH + '/dist';
// 是否是開發環境
var __DEV__ = process.env.NODE_ENV !== 'proction';
// conf
var alias = pickFiles({
id: /(conf\/[^\/]+).js$/,
pattern: SRC_PATH + '/conf/*.js'
});
// components
alias = Object.assign(alias, pickFiles({
id: /(components\/[^\/]+)/,
pattern: SRC_PATH + '/components/*/index.js'
}));
// recers
alias = Object.assign(alias, pickFiles({
id: /(recers\/[^\/]+).js/,
pattern: SRC_PATH + '/js/recers/*'
}));
// actions
alias = Object.assign(alias, pickFiles({
id: /(actions\/[^\/]+).js/,
pattern: SRC_PATH + '/js/actions/*'
}));
var config = {
context: SRC_PATH,
entry: {
app: ['./pages/app.js']
},
output: {
path: DIST_PATH,
filename: 'js/bundle.js'
},
mole: {},
resolve: {
alias: alias
},
plugins: [
new webpack.DefinePlugin({
// http://stackoverflow.com/questions/30030031/passing-environment-dependent-variables-in-webpack
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || 'development')
})
]
};
mole.exports = config;
/* webpack.dev.js */
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
var utils = require('./utils');
var PORT = 8080;
var HOST = utils.getIP();
var args = process.argv;
var hot = args.indexOf('--hot') > -1;
var deploy = args.indexOf('--deploy') > -1;
// 本地環境靜態資源路徑
var localPublicPath = 'http://' + HOST + ':' + PORT + '/';
config.output.publicPath = localPublicPath;
config.entry.app.unshift('webpack-dev-server/client?' + localPublicPath);
new WebpackDevServer(webpack(config), {
hot: hot,
inline: true,
compress: true,
stats: {
chunks: false,
children: false,
colors: true
},
// Set this as true if you want to access dev server from arbitrary url.
// This is handy if you are using a html5 router.
historyApiFallback: true,
}).listen(PORT, HOST, function() {
console.log(localPublicPath);
});
上面的配置寫好後就可以開始構建了
$ node build/webpack.dev.js
因為項目中使用了 jsx、es6、scss,所以還要添加相應的 loader,否則會報如下類似錯誤:
ERROR in ./src/pages/app.js
Mole parse failed: /Users/xiaoyan/working/webpack-react-rex-es6-boilerplate/src/pages/app.js Unexpected token (18:6)
You may need an appropriate loader to handle this file type.
編譯 jsx、es6、scss 等資源
使用 bael 和
babel-loader 編譯 jsx、es6
安裝插件:
babel-preset-es2015 用於解析 es6
安裝插件:babel-preset-react 用於解析
jsx
// 首先需要安裝 babel
$ npm i babel-core --save-dev
// 安裝插件
$ npm i babel-preset-es2015 babel-preset-react --save-dev
// 安裝 loader
$ npm i babel-loader --save-dev
在項目根目錄創建 .babelrc 文件:
{
"presets": ["es2015", "react"]
}
在 webpack.config.js 里添加:
// 使用緩存
var CACHE_PATH = ROOT_PATH + '/cache';
// loaders
config.mole.loaders = [];
// 使用 babel 編譯 jsx、es6
config.mole.loaders.push({
test: /\.js$/,
exclude: /node_moles/,
include: SRC_PATH,
// 這里使用 loaders ,因為後面還需要添加 loader
loaders: ['babel?cacheDirectory=' + CACHE_PATH]
});
3. express框架怎麼用react框架作為前端框架
不要設置視圖引擎
app.set('views','./views')
app.set('view engine','jade');
//Don't do this
然後你需要引入靜態資源
如果你使用webpack,需要把dist裡面打包好的文件作為靜態資源引入
否則需要把所有的components目錄作為靜態資源引入
你的React就是簡單的靜態資源
app.use(express.static(path.join(__dirname,'src')));
最後直接在路由返迴文件
app.get('/',function(req,res){
res.sendFile(path.join(__dirname,'index.html'))
})
4. 如何解決webpack打包後,dist文件過大的問題
去除不必要的插件
剛開始用 webpack 的時候,開發環境和生產環境用的是同一個 webpack 配置文件,導致生產環境打包的 JS 文件包含了一大堆沒必要的插件,比如 HotMoleReplacementPlugin, NoErrorsPlugin... 這時候不管用什麼優化方式,都沒多大效果。所以,如果你打包後的文件非常大的話,先檢查下是不是包含了這些插件。
提取第三方庫
像 react 這個庫的核心代碼就有 627 KB,這樣和我們的源代碼放在一起打包,體積肯定會很大。所以可以在 webpack 中設置
{
entry: {
bundle: 'app'
vendor: ['react']
}
plugins: {
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
}
}
這樣打包之後就會多出一個 vendor.js 文件,之後在引入我們自己的代碼之前,都要先引入這個文件。比如在 index.html 中
<script src="/build/vendor.js"></script>
<script src="/build/bundle.js"></script>
除了這種方式之外,還可以通過引用外部文件的方式引入第三方庫,比如像下面的配置
{
externals: {
'react': 'React'
}
}
externals 對象的 key 是給 require 時用的,比如 require('react'),對象的 value 表示的是如何在 global 中訪問到該對象,這里是 window.React。這時候 index.html 就變成下面這樣
<script src="//cdn.bootcss.com/react/0.14.7/react.min.js"></script>
<script src="/build/bundle.js"></script>
當然,個人更推薦第一種方式。
代碼壓縮
webpack 自帶了一個壓縮插件 UglifyJsPlugin,只需要在配置文件中引入即可。
{
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
}
加入了這個插件之後,編譯的速度會明顯變慢,所以一般只在生產環境啟用。
另外,伺服器端還可以開啟 gzip 壓縮,優化的效果更明顯。
代碼分割
什麼是代碼分割呢?我們知道,一般載入一個網頁都會把全部的 js 代碼都載入下來。但是對於 web app 來說,我們更想要的是只載入當前 UI 的代碼,沒有點擊的部分不載入。
看起來好像挺麻煩,但是通過 webpack 的 code split 以及配合 react router 就可以方便實現。具體的例子可以看下 react router 的官方示例 huge apps。不過這里還是講下之前配置踩過的坑。
code split 是不支持 ES6 的模塊系統的,所以在導入和導出的時候千萬要注意,特別是導出。如果你導出組件的時候用 ES6 的方式,這時候不管導入是用 CommomJs 還是 AMD,都會失敗,而且還不會報錯!
當然會踩到這個坑也是因為我剛剛才用 NodeJS,而且一入門就是用 ES6 的風格。除了這個之外,還有一點也要注意,在生產環境的 webpack 配置文件中,要加上 publicPath
output: {
path: xxx,
publicPath: yyy,
filename: 'bundle.js'
}
不然的話,webpack 在載入 chunk 的時候,路徑會出錯。
設置緩存
開始這個小節之前,可以先看下大神的一篇文章:大公司里怎樣開發和部署前端代碼。
對於靜態文件,第一次獲取之後,文件內容沒改變的話,瀏覽器直接讀取緩存文件即可。那如果緩存設置過長,文件要更新怎麼辦呢?嗯,以文件內容的 MD5 作為文件名就是一個不錯的解決方案。來看下用 webpack 應該怎樣實現
output: {
path: xxx,
publicPath: yyy,
filename: '[name]-[chunkhash:6].js'
}
打包後的文件名加入了 hash 值
const bundler = webpack(config)
bundler.run((err, stats) => {
let assets = stats.toJson().assets
let name
for (let i = 0; i < assets.length; i++) {
if (assets[i].name.startsWith('main')) {
name = assets[i].name
break
}
}
fs.stat(config.buildTemplatePath, (err, stats) => {
if (err) {
fs.mkdirSync(config.buildTemplatePath)
}
writeTemplate(name)
})
})
手動調用 webpack 的 API,獲取打包後的文件名,通過 writeTemplate 更新 html 代碼。完整代碼猛戳 gitst。
5. 如何用原生的react,webpack,es6來使用螞蟻金服的ant design組件庫
1.准備:
npm安裝以下組件
a.安裝react/antd:
npm install react react-dom antd --save
b.安裝webpack/less:
npm install webpack less --save-dev
webpack根據需要選擇使用-g安裝
c.安裝babel-loader以及其他相關package:
npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save-dev
d.選擇安裝style-loader/css-loader
npm install style-loader css-loader --save-dev
2. 配置webpack.config.js
具體配置可以查看webpack提供的例子,主要依賴的是babel-loader
babel-loader上也有webpack.config.js應該如何編寫的例子,傳送門: babel-loader
3. 編寫我們的文件(例如: demo-antd.jsx)
只使用了antd提供的Button組件。只使用了antd提供的Button組件。
ps: 對比
import { Button } from 'antd';
和
import Button from 'antd/lib/button';
後者不會將antd中所有的內容都引入,如果你只是需要Button這么一種組件的話,推薦使用後一種寫法。
4. 執行構建
webpack ./demo-antd.jsx demo-antd-bundle.js
將生成demo-antd-bundle.js文件
5. 在頁面中引入bundle文件(demo-antd-bundle.js)
執行到這一步,在瀏覽器中查看頁面可以應該可以看到一個原生樣式的button元素,因為antd並沒有將樣式使用內聯style的方式寫入js文件中。
這里我們暫時將問題一擱置,來看看問題二:組件庫的內部機制。
因為沒有深入去看過antd的源代碼,沒法詳細說明antd的在代碼編寫上的一些....怎麼說,就是『代碼為什麼這樣寫』這個問題,有興趣的話,可以去查看源碼,正如 @陳吉浩 所說,查看github上的代碼比npm下載後的代碼更舒服。
6. webpack+react能轉成java嗎
第一步:
mkdir react-demo
cd react-demo
npm init -y
npm i webpack webpack-dev-server html-webpack-plugin webpack-merge babel-loader babel-core css-loader style-loader babel-preset-react-hmre babel-preset-es2015 babel-preset-react -D
mkdir app
mkdir dist
mkdir assets
touch assets/index.tmpl.html
第二步,編輯index.tmpl.html為如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
第二步,打開你的 package.json 文件,添加如下字元串:
...
"scripts": {
"build": "webpack",
"start": "webpack-dev-server"
},
"babel":{
"presets": [
"es2015",
"react"
],
"env": {
"start": {
"presets": [
"react-hmre"
]
}
}
}
...
第三步:在根目錄新建一個 webpack.config.js 的文件,寫入如下配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const merge = require('webpack-merge');
const TARGET = process.env.npm_lifecycle_event;
process.env.BABEL_ENV = TARGET;
const PATHS = {
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'dist'),
template: path.resolve(__dirname, 'assets', 'index.tmpl.html'),
};
const common = {
entry: {
app: PATHS.app,
},
output: {
path: PATHS.build,
filename: 'bundle.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'react demo',
template: PATHS.template,
inject: 'body',
}),
],
mole: {
loaders: [{
test: /\.jsx?$/,
loaders: ['babel?cacheDirectory'],
include: PATHS.app,
}, {
test: /\.css$/,
loaders: ['style', 'css'],
include: PATHS.app,
}],
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
};
if (TARGET === 'start' || !TARGET) {
mole.exports = merge(common, {
devtool: 'eval-source-map',
devServer: {
contentBase: '/dist',
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
stats: 'errors-only',
},
plugins: [
new webpack.HotMoleReplacementPlugin(),
],
});
}
if (TARGET === 'build') {
mole.exports = merge(common, {});
}
第四步:到這里,關於react的需要的webpack方面的配置就結束了,接下來我們來寫一個很小的示例來生成一個真正的react文件。
npm i react react-dom react-router -S
touch app/App.jsx
touch app/index.jsx
編輯 App.jsx 文件如下:
import React, { Component } from 'react';
import {
Router,
Route,
Link,
IndexLink,
IndexRoute,
hashHistory,
} from 'react-router';
const activeStyle = {
color: '#53acff',
};
const Nav = () => (
<div>
<IndexLink onlyActiveOnIndex activeStyle={activeStyle} to="/">主頁</IndexLink>
<IndexLink onlyActiveOnIndex activeStyle={activeStyle} to="/address">地址</IndexLink>
</div>
);
const Container = (props) => <div>
<Nav /> { props.children }
</div>;
const Twitter = () => <div>@xiaomingplus twitter</div>;
const Instagram = () => <div>@xiaomingplus instagram</div>;
const NotFound = () => (
<h1>404.. 找不到該頁面!</h1>
);
const Home = () => <h1>你好,這是主頁。</h1>;
const Address = (props) => <div>
<br />
<Link activeStyle={{ color: '#53acff' }} to="/address">這是Twitter</Link>
<Link to="/address/instagram">這是Instagram</Link>
<h1>歡迎互關!</h1>
{ props.children }
</div>;
class App extends Component {
construct() {
}
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Container}>
<IndexRoute component={Home} />
<Route path="/address" component={Address}>
<IndexRoute component={Twitter} />
<Route path="instagram" component={Instagram} />
</Route>
<Route path="*" component={NotFound} />
</Route>
</Router>
);
}
}
export default App;
編輯 index.jsx 文件:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(
<App />, document.getElementById('root'));
ok,到這里你已經實用react-router構建了一個有路由的應用,接下來啟動這個應用吧。
npm start
用瀏覽器訪問: http://localhost:8080 ,你將看到如下界面