Open xxholly32 opened 8 years ago
在项目打包上我们这块一直没有一个完整的培训,之前是引入grunt的内容较多点,我们一开始也分享一些grunt的打包内容,希望能做一些对比,特别是在技术选型中能够区分。当然我们的目的也只有一个,就是js、css、less、html能够一套完整的规范体系,压缩,打包,合并,校验,测试等。
grunt用的比较多,直接放在项目中的一些code吧
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), /* 文件合并 */ concat: { // 将所有插件js合并成一个plugin.js dist: { src: ['public/javascript/common/plugin/*.js'], dest: 'public/javascript/common/plugin.js', }, }, // js压缩 uglify: { options: { banner: '/*! 页面公共类 <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, dist3: { src: ['public/javascript/common/global.js', 'public/javascript/common/plugin.js', 'public/javascript/common/util.js' ], dest: 'public/javascript/common/common.min.js' } }, // less插件配置 less: { main: { expand: true, src: ['public/style/less/app.less'], dest: '', ext: '.css' }, dev: { options: { compress: true, yuicompress: false } } }, // css压缩插件 cssmin: { target: { files: [{ expand: true, src: ['public/style/less/app.css'], dest: '', ext: '.min.css' }] } }, // watch插件的配置信息(监控less文件,如改变自动压缩,语法检查) watch: { // 用于监听js文件修改 js: { files: [ 'public/javascript/common/global.js', 'public/javascript/common/util.js', 'public/javascript/common/plugin/*.js' ], tasks: ['concat', 'uglify'], options: { livereload: true } }, // 用于监听less文件,当改变时自动编译成css文件 css: { files: ['public/style/less/*.less', 'public/style/less/page/*.less', 'public/style/less/common/*.less', 'public/style/less/common/minxins/*.less', 'public/style/less/common/plugin/*.less' ], tasks: ['less', 'cssmin'], options: { livereload: true } } } }); // 加载任务插件 grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-watch'); // 默认被执行的任务列表 grunt.registerTask('default', ['concat' ,'uglify', 'less', 'cssmin', 'watch']); };
grunt 比较立体和直观,但相对比较笨重,可能会有3,4百行的配置文件要写
Gulp 提供了一个不一样的解决方案,而不是依赖于各种插件的配置。Gulp 使用了一个文件流的概念。如果你熟悉 Unix,那么 Gulp 对你来说会差不多,Gulp 会提供你一些简单化的操作。在这个解决方案中,是去匹配一些文件然后操作(就是说和 JavaScript 相反)然后输出结果(比如输出在你设置的编译路径等)。
var gulp = require('gulp'); var coffee = require('gulp-coffee'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); var sourcemaps = require('gulp-sourcemaps'); var del = require('del'); var paths = { scripts: ['client/js/**/*.coffee', '!client/external/**/*.coffee'], }; // 不是所有的任务需要使用 streams // 一个 gulpfile 只是另一个node的程序,所以你可以使用所有 npm 的包 gulp.task('clean', function(cb) { // 你可以用 `gulp.src` 来使用多重通配符模式 del(['build'], cb); }); gulp.task('scripts', ['clean'], function() { // 压缩和复制所有 JavaScript (除了第三方库) // 加上 sourcemaps return gulp.src(paths.scripts) .pipe(sourcemaps.init()) .pipe(coffee()) .pipe(uglify()) .pipe(concat('all.min.js')) .pipe(sourcemaps.write()) .pipe(gulp.dest('build/js')); }); // 监听文件修改 gulp.task('watch', function() { gulp.watch(paths.scripts, ['scripts']); }); // 默认任务(就是你在命令行输入 `gulp` 时运行) gulp.task('default', ['watch', 'scripts']);
这些配置都是代码,所以当你遇到问题也可以修改,你也可以使用已经存在的 Gulp 插件,但是你还是需要写一堆模板任务。
个人感觉比grunt灵活一点,任务是针对文件而不是配的任务。
个人写的简单的gulp的例子 link to gulp!
Webpack 扩展了 CommonJs 的 require 的想法,比如你想在 CoffeeScript、Sass、Markdown 或者其他什么代码中 require 你想要的任何代码的话?那么 Webpack 正是做这方面的工作。它会通过配置来取出代码中的依赖,然后把他们通过加载器把代码兼容地输出到静态资源中。
简单来说就是我的js能够引入,css,sass,less,markdown,coffeescript,等等,看一个官方的例子
module.exports = { entry: "./entry.js", output: { path: __dirname, filename: "bundle.js" }, module: { loaders: [ { test: /\.css$/, loader: "style!css" } ] } };
# 用 npm 安装 Webpack全局依赖 $ npm install webpack -g
此时 Webpack 已经安装到了全局环境下,可以通过命令行 webpack -h 帮助。
# 安装 webpack 依赖 $ npm install webpack --save-dev
创建一个简单的html页面
<!-- index.html --> <html> <head> <meta charset="utf-8"> </head> <body> <script src="bundle.js"></script> </body> </html>
一个js入口文件:
// entry.js document.write('It works.')
然后编译 entry.js 并打包到 bundle.js:
$ webpack entry.js bundle.js
打包过程会显示日志:
Hash: e964f90ec65eb2c29bb9 Version: webpack 1.12.2 Time: 54ms Asset Size Chunks Chunk Names bundle.js 1.42 kB 0 [emitted] main [0] ./entry.js 27 bytes {0} [built]
用浏览器打开 index.html 将会看到 It works. 。
接下来添加一个模块 module.js 并修改入口 entry.js:
// module.js module.exports = 'It works from module.js.'
// entry.js document.write('It works.') document.write(require('./module.js')) // 添加模块
重新打包 webpack entry.js bundle.js 后刷新页面看到变化 It works.It works from module.js.
关于loader的文件有很多种,我这边的例子就写3种jade,css,json,还有就是babel-loader
首先来看下官方的loader种类
LIST OF LOADERS!
loader的特性
先看demo3中的css-loader
/* style.css */ body { background: yellow; }
entry.js
require("!style!css!./style.css") // 载入 style.css document.write('It works.') document.write(require('./module.js'))
安装loader
npm install css-loader style-loader
demo-loader 的例子
module.exports = { entry: './entry.js', output: { filename: 'bundle.js', }, module: { loaders: [ { test: /\.json$/, loader: "json" }, { test: /\.jade$/, loader: "jade" }, { test: /\.css$/, loader: "style!css" }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'} ] } }
这里我们的entry.js已经引入了 es6的写法: entry.js
import 'babel-polyfill'; import $ from 'jquery'; require("!style!css!./style.css"); var xxjade = require("!jade!./dir/xxjade.jade"); var json = require("!json!./dir/test.json"); console.log(json); $(xxjade()).appendTo('body');
这里我说明下babel-loader引入必须的一些配置 package.json
"babel-core": "^6.13.2", "babel-loader": "^6.2.5", "babel-polyfill": "^6.13.0", "babel-preset-es2015": "^6.13.2",
还需要引入一个.babelrc
{ "presets": [ "es2015" ] }
引入jQuery和bootstrap
webpack.config.js
var path=require('path'); var webpack = require('webpack'); module.exports = { entry: { entry : './entry.js', index : './index.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: './js/[name].debug.js', }, module: { loaders: [ { test: /\.json$/, loader: "json" }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },{ test: /\.css$/, loaders: ['style', 'css'] }, { test: /\.woff$/, loader: "url-loader?limit=10000&mimetype=application/font-woff&name=[path][name].[ext]" }, { test: /\.woff2$/, loader: "url-loader?limit=10000&mimetype=application/font-woff2&name=[path][name].[ext]" }, { test: /\.(eot|ttf|svg|gif|png)$/, loader: "file-loader" } ] }, plugins:[ new webpack.ProvidePlugin({ //加载jq $: 'jquery', jQuery: 'jquery' }), new webpack.optimize.CommonsChunkPlugin("./js/commons.js", ["index", "entry"]) ] }
实际上对bootstrap的引入并没有想象中这么友好,特别是中间的一些插件,引入起来极其困难。
index.js
import React from 'react'; import { render } from 'react-dom'; import Hello from './component.jsx'; main(); function main() { React.render(<Hello />, document.getElementById('app')); }
react 自定义组件 component.js
import React from 'react'; export default class Hello extends React.Component { render() { return <h1>Hello world</h1>; } }
var path = require('path'); module.exports = { entry: path.resolve(__dirname, 'app/index.js'), output: { path: path.resolve(__dirname, 'build'), filename: 'bundle.js' }, module: { loaders:[ { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' }, ] } };
react 和 webpack还是能够完美结合的,它的理念是把html完全嵌入到了js当中,和我们之前用到的项目jquery和bootstrap不一样。具体的react项目,再之后的react培训会细说。
其他还有一些工具bower,karma,和grunt类似。相对于grunt和gulp来说,webpack是完全不一样的框架,特别是在与js的处理,css和js的loader,es6的支持方面。也有项目gulp和webpack一起用的,gulp处理文件合并,webpack生产其他js文件等方式。但在和react的一些项目上,webpack还是首选的打包方式。
https://segmentfault.com/a/1190000002985564 https://webpack.github.io/docs/what-is-webpack.html http://zhaoda.net/webpack-handbook/preface.html
在项目打包上我们这块一直没有一个完整的培训,之前是引入grunt的内容较多点,我们一开始也分享一些grunt的打包内容,希望能做一些对比,特别是在技术选型中能够区分。当然我们的目的也只有一个,就是js、css、less、html能够一套完整的规范体系,压缩,打包,合并,校验,测试等。
grunt
grunt用的比较多,直接放在项目中的一些code吧
grunt-contrib-concat 代码合并
grunt-contrib-uglify js压缩
grunt-contrib-less less合并
grunt-contrib-cssmin css压缩
grunt-contrib-jshint js校验
grunt-contrib-watch 自动监控
grunt 比较立体和直观,但相对比较笨重,可能会有3,4百行的配置文件要写
gulp
Gulp 提供了一个不一样的解决方案,而不是依赖于各种插件的配置。Gulp 使用了一个文件流的概念。如果你熟悉 Unix,那么 Gulp 对你来说会差不多,Gulp 会提供你一些简单化的操作。在这个解决方案中,是去匹配一些文件然后操作(就是说和 JavaScript 相反)然后输出结果(比如输出在你设置的编译路径等)。
这些配置都是代码,所以当你遇到问题也可以修改,你也可以使用已经存在的 Gulp 插件,但是你还是需要写一堆模板任务。
个人感觉比grunt灵活一点,任务是针对文件而不是配的任务。
个人写的简单的gulp的例子 link to gulp!
webpack
Webpack 扩展了 CommonJs 的 require 的想法,比如你想在 CoffeeScript、Sass、Markdown 或者其他什么代码中 require 你想要的任何代码的话?那么 Webpack 正是做这方面的工作。它会通过配置来取出代码中的依赖,然后把他们通过加载器把代码兼容地输出到静态资源中。
简单来说就是我的js能够引入,css,sass,less,markdown,coffeescript,等等,看一个官方的例子
webpack 全局安装
此时 Webpack 已经安装到了全局环境下,可以通过命令行 webpack -h 帮助。
webpack 简单使用
创建一个简单的html页面
一个js入口文件:
然后编译 entry.js 并打包到 bundle.js:
打包过程会显示日志:
用浏览器打开 index.html 将会看到 It works. 。
webpack commonJS的文件引入
接下来添加一个模块 module.js 并修改入口 entry.js:
重新打包 webpack entry.js bundle.js 后刷新页面看到变化 It works.It works from module.js.
webpack loader
关于loader的文件有很多种,我这边的例子就写3种jade,css,json,还有就是babel-loader
首先来看下官方的loader种类
LIST OF LOADERS!
loader的特性
先看demo3中的css-loader
entry.js
安装loader
webpack 配置文件编写
demo-loader 的例子
这里我们的entry.js已经引入了 es6的写法: entry.js
这里我说明下babel-loader引入必须的一些配置 package.json
还需要引入一个.babelrc
webpack项目实践
引入jQuery和bootstrap
webpack.config.js
实际上对bootstrap的引入并没有想象中这么友好,特别是中间的一些插件,引入起来极其困难。
webpack 和 react 结合
index.js
react 自定义组件 component.js
webpack.config.js
react 和 webpack还是能够完美结合的,它的理念是把html完全嵌入到了js当中,和我们之前用到的项目jquery和bootstrap不一样。具体的react项目,再之后的react培训会细说。
其他的一些功能
总结
其他还有一些工具bower,karma,和grunt类似。相对于grunt和gulp来说,webpack是完全不一样的框架,特别是在与js的处理,css和js的loader,es6的支持方面。也有项目gulp和webpack一起用的,gulp处理文件合并,webpack生产其他js文件等方式。但在和react的一些项目上,webpack还是首选的打包方式。
参考文献
https://segmentfault.com/a/1190000002985564 https://webpack.github.io/docs/what-is-webpack.html http://zhaoda.net/webpack-handbook/preface.html