前面兩篇文章的例子中采用的開發(fā)方式被稱作standalone
,意思是說把所有需要用到的js文件定義好并放在<script>標(biāo)簽中,然后在另起一個<script>標(biāo)簽用于撰寫實際業(yè)務(wù)場景需要的自定義代碼;這種方式的好處是代碼的引入、撰寫和閱讀都非常清晰明了,缺點是所有源碼都暴露在html中。
通過利用gulp和其豐富插件庫可以完成對多個js文件進(jìn)行預(yù)編譯(指定一個文件,工具可以將它所有的依賴組織起來)和壓縮,最終產(chǎn)生一個具有混淆性的單js文件;詳細(xì)的gulp文檔說明請移步到這里。
簡單的合并
# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p simple_merge/src
[root@localhost ~]# cd simple_merge
# 安裝gulp打包組件和react相關(guān)的js組件
[root@localhost simple_merge]# cnpm install react react-dom gulp gulp-concat --save-dev
# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_merge]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/
# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_merge]# vim gulpfile.js
var gulp = require('gulp'),
concat = require('gulp-concat')
gulp.task('compress', function() {
return gulp.src('src/*js')
.pipe(concat('bundle.js'))
.pipe(gulp.dest('dist/'))
})
# 合并文件
[root@localhost simple_merge]# ./node_modules/gulp/bin/gulp.js compress
[21:30:29] Using gulpfile ~/simple_merge/gulpfile.js
[21:30:29] Starting 'compress'...
[21:30:29] Finished 'compress' after 53 ms
# 查看產(chǎn)出的目錄(dist)
[root@localhost simple_merge]# ls
dist gulpfile.js node_modules src
# 查看合并前的文件
[root@localhost simple_merge]# ls -alh src/
total 736K
drwxr-xr-x 2 root root 42 Mar 20 21:25 .
drwxr-xr-x 5 root root 68 Mar 20 21:30 ..
-rw-r--r-- 1 root root 606K Mar 20 21:25 react-dom.js
-rw-r--r-- 1 root root 125K Mar 20 21:25 react.js
# 查看合并后的文件
[root@localhost simple_merge]# ls -alh dist/
total 732K
drwxr-xr-x 2 root root 23 Mar 20 21:30 .
drwxr-xr-x 5 root root 68 Mar 20 21:30 ..
-rw-r--r-- 1 root root 731K Mar 20 21:30 bundle.js
小結(jié): 通過上面gulpfile.js任務(wù)管理文件中的代碼,是將兩個js文件進(jìn)行簡單的合并,可以看得出來原來兩個文件的大小分別是606k和125k,合并成單文件bundle.js后,文件的大小是731K正好是兩個文件大小的總和。
壓縮和混淆
# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p simple_uglify/src
[root@localhost ~]# cd simple_uglify/
# 安裝gulp和gulp-uglify
[root@localhost simple_uglify]# cnpm install react react-dom gulp gulp-uglify --save-dev
# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/
# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_uglify]# vim gulpfile.js
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify')
gulp.task('compress', function() {
return gulp.src('src/*js')
.pipe(concat('bundle.js'))
.pipe(uglify())
.pipe(gulp.dest('dist/'))
})
# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/
# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_uglify]# vim gulpfile.js
var gulp = require('gulp'),
uglify = require('gulp-uglify')
gulp.task('compress', function() {
return gulp.src('src/*js')
.pipe(uglify())
.pipe(gulp.dest('dist/'))
})
# 合并文件
[root@localhost simple_uglify]# ./node_modules/gulp/bin/gulp.js compress
[21:56:35] Using gulpfile ~/simple_uglify/gulpfile.js
[21:56:35] Starting 'compress'...
[21:56:39] Finished 'compress' after 3.24 s
# 查看合并前的文件
[root@localhost simple_uglify]# ls -alh src/
total 736K
drwxr-xr-x 2 root root 42 Mar 20 21:54 .
drwxr-xr-x 5 root root 88 Mar 20 21:59 ..
-rw-r--r-- 1 root root 606K Mar 20 21:53 react-dom.js
-rw-r--r-- 1 root root 125K Mar 20 21:53 react.js
# 查看合并后的文件
[root@localhost simple_uglify]# ls -alh dist/
total 216K
drwxr-xr-x 2 root root 23 Mar 20 21:59 .
drwxr-xr-x 5 root root 88 Mar 20 21:59 ..
-rw-r--r-- 1 root root 216K Mar 20 21:59 bundle.js
小結(jié): 僅僅是將兩個源碼文件進(jìn)行合并其實并沒有什么意義,這里將采用uglify插件對合并后的文件進(jìn)行壓縮和混淆。
解決依賴問題
上面兩個例子都是針對源碼庫文件進(jìn)行合并、壓縮和混淆,實際上意義也不大,因為這兩個代碼跟項目業(yè)務(wù)代碼并沒有直接作用。所以這里將會單獨列出一個業(yè)務(wù)代碼的js文件,并通過gulp的相關(guān)插件來完成依賴問題解決。
# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p spa_jsx/src
[root@localhost ~]# cd spa_jsx/
# 安裝相關(guān)插件
[root@localhost spa_jsx]# cnpm install babel babel-core babel-preset-es2015 babel-preset-react babelify gulp gulp-uglify gulp-streamify gulp-uglify browserify vinyl-source-stream react react-dom react-remarkable --save-dev
# 創(chuàng)建.babelrc文件(聲明支持es2015和react)
[root@localhost spa_jsx]# vim .babelrc
{ presets: ["es2015", "react"] }
# 創(chuàng)建源碼組件(Component)文件
[root@localhost spa_jsx]# vim src/markdown_editor.js
import React, {Component} from 'react';
import Remarkable from 'remarkable';
class MarkdownEditor extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {value: 'Type some *markdown* here!'};
}
handleChange(e) {
this.setState({value: e.target.value});
}
getRawMarkup() {
var md = new Remarkable();
return { __html: md.render(this.state.value) };
}
render() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<textarea onChange={this.handleChange}
defaultValue={this.state.value} />
<h3>Output</h3>
<div className="content"
dangerouslySetInnerHTML={this.getRawMarkup()} />
</div>
);
}
}
export default MarkdownEditor;
# 創(chuàng)建源碼模版(JSX)文件
[root@localhost spa_jsx]# vim src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './markdown_editor';
ReactDOM.render(
<App />,
document.getElementById('root')
);
# 創(chuàng)建gulpfile.js任務(wù)配置管理文件.
[root@localhost spa_jsx]# vim gulpfile.js
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
browserify = require('browserify'),
babelify = require('babelify'),
source = require('vinyl-source-stream'),
streamify = require('gulp-streamify')
gulp.task('compress', function() {
process.env.NODE_ENV = 'production';
// 這里僅制定單個index.js文件, browserify會根據(jù)
// import和from關(guān)鍵字去提取相關(guān)的依賴庫。
return browserify('src/index.js')
.transform(babelify)
.bundle()
.pipe(source('bundle.js'))
.pipe(streamify(uglify()))
.pipe(gulp.dest('dist/'))
})
# 編譯文件(指的是根據(jù)index.js去尋找相關(guān)的依賴代碼,然后整合、壓縮和混淆)。
[root@localhost spa_jsx]# ./node_modules/gulp/bin/gulp.js compress
# 查看編譯前的源文件
[root@localhost spa_jsx]# ls -alh src/
total 8.0K
drwxr-xr-x 2 root root 48 Mar 21 00:18 .
drwxr-xr-x 5 root root 104 Mar 21 01:19 ..
-rw-r--r-- 1 root root 169 Mar 21 00:07 index.js
-rw-r--r-- 1 root root 902 Mar 21 00:06 markdown_editor.js
# 查看合并后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 336K
drwxr-xr-x 2 root root 23 Mar 21 01:19 .
drwxr-xr-x 5 root root 104 Mar 21 01:19 ..
-rw-r--r-- 1 root root 334K Mar 21 01:19 bundle.js
提示: .babalrc文件用來聲明babel環(huán)境變量,像.bashrc一樣。如果不聲明.babelrc的話,那么執(zhí)行g(shù)ulpfile.js時就會報錯。 若不想聲明.babelrc文件,但又要編譯es2015的代碼,那么可以在將gulpfile.js文件中的.transform(babelify)
改為.transform(babelify, {presets: ["es2015", "react"]})
即可。
小結(jié): 這個例子是提供單個index.js文件,browserify會根據(jù)import和from關(guān)鍵字去提取相關(guān)的依賴庫。
使用browserify壓縮混淆(不采用gulp)
不使用.babelrc
# 安裝 uglifyify
[root@localhost spa_jsx]# cnpm install uglifyify --save-dev
# 清除原來的文件
[root@localhost spa_jsx]# rm dist/* -rf
# 壓縮混淆
# 這里要特別注意:命令中的[]兩邊一定要有空格,否則會報模塊找不到。
[root@localhost spa_jsx]# NODE_ENV=productioin browserify -t [ babelify --presets [ react es2015 ] ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js
# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 472K
drwxr-xr-x 2 root root 20 Mar 23 02:16 .
drwxr-xr-x 5 root root 106 Mar 22 21:47 ..
-rw-r--r-- 1 root root 471K Mar 23 02:17 bundle.js
使用.babelrc
# 清除原來的文件
[root@localhost spa_jsx]# rm dist/* -rf
# 創(chuàng)建.babelrc文件
[root@localhost spa_jsx]# vim .babelrc
{ presets: [ "react", "es2015" ] }
# 壓縮混淆
[root@localhost spa_jsx]# NODE_ENV=productioin browserify -t [ babelify ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js
# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls dist/ -alh
total 472K
drwxr-xr-x 2 root root 20 Mar 23 02:16 .
drwxr-xr-x 5 root root 122 Mar 23 02:19 ..
-rw-r--r-- 1 root root 471K Mar 23 02:20 bundle.js
使用npm + browserify
# 在package.json中加入npm腳本指令
[root@localhost spa_jsx]# cat package.json
{
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"babel-preset-react": "^6.23.0",
"babelify": "^7.3.0",
"browserify": "^14.1.0",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-sourcemaps": "^2.4.1",
"gulp-streamify": "^1.0.2",
"gulp-uglify": "^2.1.2",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-remarkable": "^1.1.1",
"reactify": "^1.1.1",
"uglifyify": "^3.0.4",
"vinyl-source-stream": "^1.1.0"
},
"scripts": {
"clean": "rm -rf dist/*"
"build": "NODE_ENV=productioin browserify -t [ babelify ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js"
}
}
# 執(zhí)行指令(清除目錄)
[root@localhost spa_jsx]# npm run clean
> @ clean /root/spa_jsx
> rm -rf dist/*
# 壓縮混淆
[root@localhost spa_jsx]# npm run build
# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 472K
drwxr-xr-x 2 root root 23 Mar 23 02:44 .
drwxr-xr-x 5 root root 122 Mar 23 02:43 ..
-rw-r--r-- 1 root root 471K Mar 23 02:44 bundle.js