03_预编译和混淆

前面两篇文章的例子中采用的开发方式被称作standalone,意思是说把所有需要用到的js文件定义好并放在<script>标签中,然后在另起一个<script>标签用于撰写实际业务场景需要的自定义代码;这种方式的好处是代码的引入、撰写和阅读都非常清晰明了,缺点是所有源码都暴露在html中。

通过利用gulp和其丰富插件库可以完成对多个js文件进行预编译(指定一个文件,工具可以将它所有的依赖组织起来)和压缩,最终产生一个具有混淆性的单js文件;详细的gulp文档说明请移步到这里。

简单的合并

# 创建项目目录结构
[root@localhost ~]# mkdir -p simple_merge/src
[root@localhost ~]# cd simple_merge

# 安装gulp打包组件和react相关的js组件
[root@localhost simple_merge]# cnpm install react react-dom gulp gulp-concat --save-dev

# 将react.js和react-dom.js文件复制到src目录中.
[root@localhost simple_merge]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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

# 查看产出的目录(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

小结: 通过上面gulpfile.js任务管理文件中的代码,是将两个js文件进行简单的合并,可以看得出来原来两个文件的大小分别是606k和125k,合并成单文件bundle.js后,文件的大小是731K正好是两个文件大小的总和。

压缩和混淆

# 创建项目目录结构
[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文件复制到src目录中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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文件复制到src目录中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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

小结: 仅仅是将两个源码文件进行合并其实并没有什么意义,这里将采用uglify插件对合并后的文件进行压缩和混淆。

解决依赖问题

上面两个例子都是针对源码库文件进行合并、压缩和混淆,实际上意义也不大,因为这两个代码跟项目业务代码并没有直接作用。所以这里将会单独列出一个业务代码的js文件,并通过gulp的相关插件来完成依赖问题解决。

# 创建项目目录结构
[root@localhost ~]# mkdir -p spa_jsx/src
[root@localhost ~]# cd spa_jsx/

# 安装相关插件
[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

# 创建.babelrc文件(声明支持es2015和react)
[root@localhost spa_jsx]# vim .babelrc 
{ presets: ["es2015", "react"] }

# 创建源码组件(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;


# 创建源码模版(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')
);


# 创建gulpfile.js任务配置管理文件.
[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会根据
    // import和from关键字去提取相关的依赖库。
    return browserify('src/index.js')   
           .transform(babelify)
           .bundle()
           .pipe(source('bundle.js'))
           .pipe(streamify(uglify()))
           .pipe(gulp.dest('dist/'))
})


# 编译文件(指的是根据index.js去寻找相关的依赖代码,然后整合、压缩和混淆)。
[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环境变量,像.bashrc一样。如果不声明.babelrc的话,那么执行gulpfile.js时就会报错。 若不想声明.babelrc文件,但又要编译es2015的代码,那么可以在将gulpfile.js文件中的.transform(babelify)改为.transform(babelify, {presets: ["es2015", "react"]})即可。
小结: 这个例子是提供单个index.js文件,browserify会根据import和from关键字去提取相关的依赖库。

使用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

# 创建.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"
  }
}

# 执行指令(清除目录)
[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

使用webpack

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容