Babel

| babel安装
| ES6转ES5 babel-preset-es2015
| jsx文件的转换 npm i babel-preset-react
| .babelrc 文件配置 presets来解析
| 加UMD模块,可以自带模块代码

插件

$ npm install babel-cli         // babel的命令行cli

$ npm install --save-dev babel-preset-react        // 转换JSX语法并去掉注释

    .babelre配置  { "presets": ["env", "react", "stage-2"] }


$ npm install --save-dev babel-preset-env        // 转义器将JS的 ES6、7转成ES5,官方废弃了ES2015/ES2016/ES2017使用babel-preset-env 来代替

    .babelre配置  { "presets": ["env"] }

$ npm install --save-dev babel-loader            // webpack的使用babel的加载器

$ npm install -save-dev babel-polyfill        // babel默认只转新的javascript语法,不会转新的API, 如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,需要使用babel-polyfill

Babel

babel支持的使用场景非常多,可以在浏览器中使用(browser)也可以在命令行(cli),还可以是我们常见的gulp和webpack中

一、安装:

    $ npm install babel-cli  babel-preset-env                    // 包括了: babel、babel-node、babel-core、babel-register

    // PolyFill 用于语法转换(如箭头函数)
    $ npm install --save-dev babel-polyfill                

    // babel-preset-react用于JSX语法转换Flow
    $ npm install --save-dev babel-preset-react                // .babelrc中需要加react

    $ touch .babelrc

        { "presets": ["env", "react"] }


        1、babel-register模块改写require命令,为它加上一个钩子。require加载.js、.jsx、.es和.es6后缀名的文件,就会先用Babel进行转码。

            npm install --save-dev babel-register

            // 先加载babel-register,这样就会不在对index.js进行转码了
            require("babel-register");
            require("./index.js");

        2、浏览器环境

            下载babel-core: npm install babel-core@5

            <!-- 引用browser.js -->
            <script src="node_modules/babel-core/browser.js"></script>
            <!-- type值为text/babel -->
            <script type="text/babel">
                // 这里写es6的代码
            </script>


二、babel用处

    1、将ES6转成ES5代码 babel-preset-es2015

        npm i babel-preset-es2015 --save-dev

        需要创建一个 .babelrc 文件
        {
              "presets": ["es2015"]
        }

    2、babel-polyfill: 可以在在浏览器直接解析    npm i babel-polyfill --save-dev

    3、React的JSX代码: npm i babel-preset-react --save-dev

        对.babelrc文件配置
        {
              "presets": ["es2015", "react"]
        }


三、执行编译

    # babel main.js     // 将文件直接编译

    # babel main.js --out-file  main-component.js     // 编译文件 - 将main.js编译成一个main-component.js, 缩定--out-file 写成 -o

    # babel src --out-dir build   // 编译目录 - 将src目录下的所有文件编译到build目录下,--out-dir简写 -d

    # babel --watch main.js --out-file main-component.js  --source-maps  // --watch 侦听文件的变化,--source-maps 会在文件打出文件的目录, 简写 -w

    # babel src --out-dir lib  // 编译目录,src目录下的所有文件进行编辑并放到lib文件夹中


四、浏览器上直接编译 browser.js

    可以直接转换,不需要执行编译命令

    1、加载需要文件
        babel-core/browser.js 
        babel-core/browser-polyfill.js     // 修补浏览器工具的,浏览器不支持的时候需要它

    2、<script>调用
        type中必须写成 'text/babel'
        <script src="main.js" type="text/babel"></script>

babel-cli

Babel 附带一个内置的 CLI,可用于从命令行编译文件, 用于执行命令

// 安装
$ npm install --save-dev babel-cli

// 执行
package.json中配置

    "scripts": {
        "build": "babel src -d build",        // 通过babel将src目录下的文件全部转译到build目录
    },

plugins

将运行代码分三个阶段:解析、转换、生成

.babelrc文件

    {
        "presets": [
            "es2015",            // es2015、es2016、es2017
            "react",
            "stage-2"            // stage-0...stage-4
        ]
    }

Stage-X 阶段

$ npm install --save-dev babel-preset-stage-0        // 安装

.babelrc
{
    "presets": ["stage-0"] 
}

Stage 0 - 稻草人: 只是一个想法,可能是 babel 插件

Stage 1 - 提案: 初步尝试

Stage 2 - 初稿: 完成初步规范

Stage 3 - 候选: 完成规范和浏览器初步实现

Stage 4 - 完成: 将被添加到下一年度发布

Balel 与 Gulp结合

// 安装gulp 和 gulp-bable包
$ npm i gulp gulp-babel --save

gulpFile:

    var gulp = require('gulp');
    var babel = require('gulp-babel');

    gulp.task('babelTask', function(){
        return gulp.src('./src/*.js')
            .pipe(babel())
            .pipe(gulp.dest('babelTask'))
    })

    gulp.task('default',['babelTask']);

Babel 与 Webpack结合

// 安装webpack和babel需要的包
$ npm install babel-loader babel-core babel-preset-es2015 webpack --save-dev

webpack.config.js:

    var webpack = require('webpack');
    var path = require('path');

    module.exports = {

        /* 页面入口 - 单入口文件 */
        entry: {
                index : './src/js/webpackPackMain.js'          // 单入口文件
        },

        output: {
                path: './dist/js/',
                filename: '[name].min.js?[hash]'            // [hash] 将文件输出后加一个hash值
        },

        //加载器配置
        module: {
                loaders: [
                    <!-- { test: /\.css$/, loader: 'style-loader!css-loader'},
                    { test: /\.js$/, loader: 'jsx-loader?harmony'},
                    { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},

                    // ?limit=8192  limit设置小于8k的图片转成64位编码,大小8于不会被转码
                    { test: /\.(png|jpg|woff|eot|ttf|svg|gif)$/, loader: 'url-loader?limit=8192'}, -->

                    // es6转es5
                    {
                        test: /\.js$/,
                        exclude: /(node_modules|bower_components)/,
                        loader: 'babel-loader',
                        query: {
                            presets: ['es2015']
                        }
                    }
                ]
        }
    };

| https://babel.docschina.org/ // 官网

Gulp

gulp

https://github.com/gulpjs

可以自动化执行任务的工具,主要用于生产环境和开发环境的文件处理

Gulp是一个新的基于流的管道式构建系统,需要很少的配置并且更快

主要作用:

    1、多个js或css文件合并、压缩

    2、Sass或Less的编译

    3、图像的压缩

    3、实时刷新页面的本地服务器

gulp对按需加载不好做到,如A和B页面都依赖base.js,但又各依赖a.js和b.js,这种情况gulp打包是将三个都包括了,所以css和html部分gulp来处理,js的webpack处理

安装、使用

$ npm install -g gulp     // 全局安装Gulp

$ npm init    // 创建package.json 项目描述文件

$ npm install --save-dev gulp    // 作为项目的开发依赖(只在开发时用,不会发布到线上)

$ touch gulpfile.js

    var gulp = require('gulp');
    gulp.task('default', function(){

    })

$ gulp     // 运行gulp

gulp 方法

1、gulp.src(): 获取到想要处理的文件流,可以是一个字符串或者数组,返回一个stream

    1)、*.{png,jpg,gif,ico}      // 匹配文件

    2)、**/*.html        // 目录用**、文件名用*

    gulp.task('count', function(){
        gulp.src(['aa.html', 'bb.html'])    // 或 gulp.src('src/*.html');
            .pipe(gulp.uglify())
    })

2、gulp.pipe(): 将获取到的文件流通过pipe()导入到gulp的插件中进行处理

3、gulp.dest(): 用来写文件的,插件处理完,通过dest()处理完成后把流中的内容写到指定的文件中

    var gulp = require('gulp');
    gulp.src('js/main.js')                 // 获取文件的流的api
        .pipe(gulp.uglify())            // 文件进行压缩
        .pipe(gulp.dest('dist/[name].min.js'));     // 写文件的api


4、gulp.task('任务名' [依赖任务], callback): 定义任务,依赖任务会在当前任务执行前完成

    gulp.task('test', ['styles', 'task'], function() {
        // 将你的默认的任务代码放在这
    });

    # gulp test     // 执行任务


5、gulp.watch('要监视文件的匹配模式', [要执行的task定义的任务], callback): 监视文件的变化,变化后来执行定义的任务

gulp 执行命令

-v 或 --version 会显示全局和项目本地所安装的 gulp 版本号

--gulpfile 手动指定一个 gulpfile 的路径,这在你有很多个 gulpfile 的时候很有用。这也会将 CWD 设置到该 gulpfile 所在目录

--cwd dirpath 手动指定 CWD。定义 gulpfile 查找的位置,此外,所有的相应的依赖(require)会从这里开始计算相对路径

-T 或 --tasks 会显示所指定 gulpfile 的 task 依赖树

--tasks-simple 会以纯文本的方式显示所载入的 gulpfile 中的 task 列表

--color 强制 gulp 和 gulp 插件显示颜色,即便没有颜色支持

--no-color 强制不显示颜色,即便检测到有颜色支持

--silent 禁止所有的 gulp 日志

Gulp 扩散操作

1、复制单个文件task

    gulp.task('copy-html',function(){
        return gulp.src('app/index.html').pipe(gulp.dest('dist'));
    });


2、复制多个文件

    gulp.task('copy-images',function(){
        return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
    });

    gulp.task('copy-other',function(){
        return gulp.src(['app/css/*.css','app/js/*.js'],{base:'app'}).pipe(gulp.dest('dist'));
    });

gulp 插件

https://gulpjs.com/plugins/

$ gulp
$ gulp-babel babel-core babel-preset-env        // ES6转ES5
$ babel-plugin-transform-runtime        // ES6转ES5运行时转换
$ gulp-uglify            // 压缩js
$ gulp-concat            // 合并js
$ gulp-jshint            // js语法检测
$ gulp-less              // less编译
$ gulp-ruby-sass        // sass编译
$ gulp-minify-css        // css压缩
$ gulp-css-base64        // 生成64位图标
$ gulp-htmlmin           // html压缩
$ gulp-file-include        // includer嵌入到另一个html文件
$ gulp.spritesmith       // 雪碧图
$ gulp-imagemin          // 压缩图片
$ imagemin-pngquant      // 图片的深度压缩
$ gulp-cache             // 只压缩修改的图片
$ gulp-rev-append        // 加版本号,给页面文件引用的js和css资源
$ gulp-autoprefixer     // 自动补齐前缀,根据设置浏览器版本自动处理浏览器前缀 CSS3的前缀
$ gulp-react             // react区分jsx文件进行转换
$ gulp-webpack           // webpack
$ gulp-amd-optimizer     // requirejs 压缩
$ vinyl-buffer           // 流缓存
$ merge-stream           // 合并流
$ gulp-watch             // 侦听变化自动执行task
$ gulp-livereload        // 当监听文件发生变化时,浏览器自动刷新页面
$ gulp-header            // 注释自定义插件
$ gulp-rimraf            // 清除文件
$ gulp-clean             // 删除文件或目录
$ gulp-plumber           // 错误提示
$ gulp-notify            // 消息提示
$ gulp-rename            // 重命
$ gulp-connect           // gulp的服务器
$ gulp-browserify          // 
$ gulp-open                // 打开浏览器
$ gulp-md5-plus            // 生成md5码

一、gulpfile.js中引用插件   

    var uglify = require('gulp-uglify');


二、gulp-load-plugins 模块化管理插件

    1、一般情况下,gulpfile.js中的模块需要一个个加载。

        var gulp = require('gulp')
               jshint = require('gulp-jshint'),
            uglify = require('gulp-uglify'),
            concat = require('gulp-concat');

        gulp.task('js', function () {
               return gulp.src('js/*.js')
                  .pipe(uglify())
                  .pipe(concat('app.js'))
                  .pipe(gulp.dest('build'));
        });


    2、gulp-load-plugins 会加载 package.json中存在下面的插件依赖:

        "devDependencies": {
            "gulp": "^3.9.0",
            "gulp-uglify": "^2.6.0",
            "gulp-concat": "^2.2.0"
        }

        var gulp = require('gulp');
        var $ = require('gulp-load-plugins')();            // 加载gulp-load-plugins插件,并立刻运行

        使用:$.uglify  可以省去单个引入
        gulp.task('add', function(){
            gulp.src(['js/main.js'])
                .pipe($.concat)
                .pipe($.uglify)            // $.uglify就可以调用了
                .pipe(gulp.dest('dist/[name].min.js'));    // 如果不改变文件名就直接写成 dist/js/
        })

gulp + webpack构建多页面

├── .DS_Store
├── src                // 生产目录
├── dist            // 发布目录
├── gulpfile.js
├── node_modules
└── package.json

| 参考资料
| http://www.gulpjs.com.cn/ gulp中文网
| http://www.ydcss.com/archives/category/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7
| http://www.gulpjs.com.cn/docs/recipes/ gulp 技巧集
| http://www.gulpjs.com.cn/docs/api/ gulp api
| http://www.techug.com/gulp gulp使用指南
| http://www.w3ctech.com/topic/134 gulp开发教程
| http://www.qianduancun.com/nodejs/33.html gulp-load-plugins[模块化管理插件]
| http://segmentfault.com/a/1190000003098076#articleHeader0 利用 gulp 处理前端工作流程
| http://www.cnblogs.com/2050/p/4198792.html 前端构建工具gulpjs的使用介绍及技巧
| https://www.cnblogs.com/weixing/p/5474324.html
|
| 多页面
| https://www.cnblogs.com/maskmtj/archive/2016/07/21/5597307.html
| https://github.com/fwon/gulp-webpack-demo
|
| 文件流
| http://segmentfault.com/a/1190000000519006 nodejs中流(stream)的理解
| http://www.it165.net/pro/html/201406/15924.html Node.js Stream(流)的学习笔记
| http://segmentfault.com/a/1190000000357044 Node 中的流(Stream)
|
| Promise
| http://segmentfault.com/a/1190000002591145 深入理解Promise实现细节
| http://www.tuicool.com/articles/fe6Jbyz Promise实现原理
| http://segmentfault.com/a/1190000003028634 异步编程 promise模式 的简单实现
| http://sentsin.com/web/861.html

webpack插件类

插件类详解

  • webpack-dev-server - webpack自带服务

    webpack自带的插件

    • CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin - 提取公用部分

    外部加载插件

    • HotModuleReplacementPlugin() - 热替换
    • html-webpack-plugin - 解析html模板
    • UglifyjsWebpackPlugin - js压缩
    • web-webpack-plugin - 与html-webpack-plugin类型国内人写的https://github.com/gwuhaolin/web-webpack-plugin/blob/master/readme_zh.md
    • extract-text-webpack-plugin - 单独打包css文件
    • open-browser-webpack-plugin - 资源构建成功后自动打开浏览器
    • clean-webpack-plugin - 清除文件夹,添加hash后,会导致改变文件内容重新打包时文件名不同越来越多,使用clean-webpack-plugin

    • babel-plugin-react-transform react-transform-hmr - react的热更新, 需要在配置bable.rc

    • ExtractTextPlugin - 将js中引用的css文件抽取出一个单独的css文件
    • webpack-merge - 合并数组、函数
    • webpack-dev-middleware - devServer就是基于webpack-dev-middleware和ExpressJS来实现的
    • imagemin-webpacl-plugin - 压缩图片
    • webpack-spritesmith - 制作雪碧图
    • HotModuleReplacementPlugin - devServer热更新

HotModuleReplacementPlugin() 热替换

webpac-dev-server支持模块热替换,在前端代码变动的时候无需整个刷新页面,只把变化的部分替换掉。使用HMR功能也有两种方式: 命令行方式和Node.js API。

1、script: {
“start”: “webpack –config webpack.config.js”,
“dev”: “webpack-dev-server –inline –hot”
}

2、webpack.config

entry: [
  'webpack/hot/dev-server',
  path.resolve(__dirname, 'src/index.js')
],
devServer: {
  hot: true       // 这里需要配置与HotModuleReplacementPlugin配合使用
},
plugins: [
  new webpack.HotModuleReplacementPlugin(),
]

注意,devServer开启不会自动编译,解决就在启动一个执行webpack的侦听

html-webpack-plugin

创建HTML文件,或将以有的HTML文件移动目录

$ npm i –save-dev html-webpack-plugin // 安装

const HtmlWebpackPlugin = require(‘html-webpack-plugin’); // 引用插件

option 选项

plugins: [
new HtmlWebpackPlugin({

  // 改变页面的<title>标签的内容 
  title: '首页',                   // 页面调用<%= htmlWebpackPlugin.options.title %|

  // 模版地址
  template: path.resolve(basePath, 'main.html'),

  // 构建后的文件名和目录
  filename: path.resolve(buildPath, 'main.html'),

  // chunks这个参数告诉插件要引用entry里面的哪几个入口
  chunks:['main'],

  // 不引用的模块
  excludeChunks: [],

  // 要把script插入标签里 head or body
  inject:'body',

  // 设置meta标签
  meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'},

  // 基础路径
  base: 'https://example.com/path',

  // js或css文件是否加时间缀
  hash: true,

  // 缓存
  cache: true,

  // xhtml
  xhtml: true, 

  minify: {
    collapseWhitespace: true,           // 去掉空格
    removeComments: true,               // 移除注释
    removeRedundantAttributes: true,    
    removeScriptTypeAttributes: true,
    removeStyleLinkTypeAttributes: true,
    useShortDoctype: true
  }
}),

],

open-browser-webpack-plugin

devServer下资源构建成功后自动打开浏览器 — 已可以在命令中配置

$ npm install open-browser-webpack-plugin –save-dev

var OpenBrowserPlugin = require(‘open-browser-webpack-plugin’);

plugin: [
new OpenBrowserPlugin({ url: ‘http://localhost:3000' })
]

也可以使用在package.json中加 –open

"scripts": {
  "start": "webpack-dev-server --hot --inline --open",
}

https://github.com/baldore/open-browser-webpack-plugin

CleanWebpackPlugin

用于删除目录、文件

$ npm install –save-dev clean-webpack-plugi

const CleanWebpackPlugin = require(‘clean-webpack-plugin’);

plugins: [
new CleanWebpackPlugin(),
],

https://github.com/johnagan/clean-webpack-plugin

UglifyjsWebpackPlugin

压缩文件

$ npm i -D uglifyjs-webpack-plugin

const UglifyJsPlugin = require(‘uglifyjs-webpack-plugin’)
module.exports = {
plugins: [
new UglifyJsPlugin()
]
}

extract-text-webpack-plugin

单独打包css文件

$ npm i -D extract-text-webpack-plugin

clean-webpack-plugin 清除文件夹

$ npm install clean-webpack-plugin –save-dev

const CleanWebpackPlugin = require(‘clean-webpack-plugin’);
plugins: [
new CleanWebpackPlugin([‘dist’]),
new HtmlWebpackPlugin({
title: ‘Output Management’
})
]

react的热替换

$ npm install –save-dev babel-plugin-react-transform react-transform-hmr

.babelrc配置
{
“presets”: [“react”, “env”],
“env”: {
“development”: {
“plugins”: [[“react-transform”, {
“transforms”: [{
“transform”: “react-transform-hmr”,
“imports”: [“react”],
“locals”: [“module”]
}]
}]]
}
}
}

| https://zhuanlan.zhihu.com/p/43778591
| https://www.webpackjs.com/concepts/ 中文文档

webpack

模块化

模块化分为AMD、CMD、CommonJS、ES6四类

一、CommonJS 

    Node、webpack使用的CommonJS规范, require加载是同步的

    // 导入
    const moduleA = require('./moduleA');
    moduleA.someFun(1,2);            // 需要等moduleA加载后在执行,这里是同步

    // 导出
    module.exports = moduleA.someFunc


二、AMD 异步加载模块

    可异步加载依赖模块,可并行加载多个依赖,可以运行浏览器和node环境下,缺点是需要加载AMD的库才能使用,常用的require.js

    // 定义模块
    define('moduleA', [依赖文件], function(jquery){
            var someFun = (x, y) => { return x + y}
            return {
                someFun,
            }
    })

    // 导入和使用
    require(['moduleA'], function(moduleA){
        module.someFun(1,2);
    })


三、ES6

    JS的标准化模块加载,会逐渐的取代commonJS和AMD

    // 导入
    import React from 'react'
    import ReactDOM, { render } from 'react-dom';

    // 导出
    export function hello(){ ... }
    export default {
        ...
    }
    export { fn1, fn2 }


四、CMD 同步加载模块

    代表seajs

    // 定义模块
    define(function(require,exports,module){
        var $ = require('jquery');        // 用来加载模块

        exports.sayHello = function(){    // 导出的接口
            ...
        }
    });

构建工具的什么用

1、代码转换 - 将ES6转ES5, 将SCSS转成css

2、文件优化 - 压缩JS、CSS、HTML代码,压缩合并图片

3、代码分割 - 提取多个页面的公共代码,提取首屏不需要执行代码,其它的异步加载

4、模块合并 - 将多个模块合并成一个文件

5、自动刷新 - 监听本地代码变化,并自动构建和刷新浏览器

6、代码校验 - 校验代码是否符合规范

7、自动发布 - 自动构建出线上发布代码并传输给发布系统

webpack安装和命令

$ npm i -D webpack webpack-cli         // 安装稳定版本,4版本以上需要装webpack-cli, -D是--save-dev的缩写

    npm i -D webpack@3.10.0                  // 安装指定版本

$ touch webpack.config.js // 创建配置文件

一、配置npm运行命令

    "scripts": {
        "start": "webpack --config webpack.config.js"
    }
    $ npm start         // 执行


二、webpack命令

    1、webpack            // 最基本的启动webpack命令

    2、webpack --config XXX.js   // 如果默认的配置文件不叫webpack.config.js,就需要在这指定配置文件的名称

        script: {
            "build": "webpack --config production.config.js",
            "dev": "webpack --config development.config.js"
        }

    3、webpack -w         // watch方法,时实预览进行打包 相当于 --watch 

    4、webpack -p         // 对打包后的文件进行压缩

    5、webpack -d         // 提供SourceMaps,方便调试

    6、webpack --colors     // 输出结果带彩色,比如: 会用红色显示耗时较长的步骤

    7、webpack --profile // 输出性能数据,可以看到每一步的耗时

    8、webpack --display-modules     // 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块

    9、webpack --progress --colors   // 展示一些进度条,同时增加颜色

    10、webpack --display-error-details    // 打印出错在哪个文件和行

Entry

entry是配置模块的入口,执行构建开始时递归解析所有的入口依赖,配置值: string | object | array

// 单入口
module.exports = {
    entry: './src/main.js'
}

// 多入口
module.exports = {
    entry: {
        main: ["./main.js", "./list.js"]
    }
}

// 多入口,app(应用主入口),vendors(公共库)入口
module.exports = {
    entry: {
        main: './src/main.js',
        list: './src/list.js',
        vendors: './src/jquery.js'                // 加载第三方模块
    }
}

Output

配置 output 选项可以控制 webpack 如何向硬盘写入编译文件

output的配置属性:

1、path: 输出的目录,绝对路径

2、filename: 用于输出文件的文件名

    变量: 1) id chunk 的唯一标识从0开始      2)name chunk 的名称        3)hash 输出hash值        4)chunkhash 内容的hash值

    filename: 'bundle.js'

    filename: '[name].js'            // 用于多入口

    filename: '[chunkhash].js'    // 一个随机数,入口为entry chunk

    filename: '[name].js[hash]'    // 带hash值 [hash:8] 代表8位的hash,默认20位

3、publicPath: 复杂项目里会有一些构建出的资源需要异步加载,加载这些异步资源需要对应的URL

    output: {
        filename: '[name]_[chunkhash:8].js',
        publicPath: 'https://cdn.example.com/assets/'            // 发布到线上的HTML <script src="https://cdn.example.com/assets/main.12345678.js"</script>
    }

Loader

它的基本工作流是将一个文件以字符串的形式读入,对其进行语法分析及转换, 预处理 CoffeeScript、    TypeScript、ESNext (Babel)、Sass、Less、Stylus

1、rules: 配置模块的读取和解析,将所有引用资源(.css、.html、.scss、.jpg)作为模块处理

2、条件匹配: 通过test、include、exclude三个配置项来选中loader规则文件

    test: 匹配哪些文件

    include: 指定一个目录下的所有文件,可以加快webpack的搜索速度

    exclude: 排除某个目录,不在这个目录搜索文件

3、应用规则: 对选中的文件通过usr配置来应用loader

4、重置顺序: 默认从右向左执行, 通过enforce选项将其中一个loader的顺序放到最前或最后

module: {
rules: [
        {
    test: /(\.jsx|\.js)$/,
    use: {
      loader: "babel-loader",
    },
            include: [path.resolve(__dirname, 'src)],        // 只在src目录下搜索js文件
  }
  {
    test: /\.css$/,
    use: ["style-loader", "css-loader?minimize", "sass-loader"],        // minimize 压缩css
            exclude: [/node_modules/]                // 除了node_modules目录不搜索
  }
]

}

插件: npm install --save-dev css-loader

resolve

webpack启动后会从入口找出所有的依赖模块,resolve配置如何寻找模块对应的文件

1、alias 让模块引入变得简单

    import $ from '/js/lib/jquery.min.js';      开发中需要引入jquery就需要写这类路径

    通过alias来解决
    resolve: {
        alias: {
            jquery: path.resolve(__dirname, "/js/lib/jquery.min.js"),
        },
        extensions: ['', '.js', '.vue', '.scss', '.css']             //设置require或import的时候可以不需要带后缀
    }

    引用
    import $ from 'jquery';        // jquery就会被替换成依赖的路径

plugins

plugins扩展webpack功能

一、webpack自带插件,可以直接使用

    pulgins: [
        new webpack.optimize.UglifyJsPlugin(),
        new webpack.optimize.CommonsChunkPlugin({    // webpack自带插件在webpack.optimize内
            name: 'vendor',                                // 上面入口定义的节点组
            filename: 'jquery.vendor.js?[hash]'     // 最后生成的文件名
        })
    ]

二、非自身插件,需要先调用插件

    例: main.js

        require('./main.css')
        const show = require('./show.js)
        show(1,2)

    webpack.config.js
    // 将引用的css文件提取出来 
    const ExtractTextPlugin = require('extract-text-webpack-plugin');        

    pulgins: [
        new ExtractTextPlugin({
            filename: '[name].[contenthash:8].css',            // main.11ad8d2c.css
            allChunks: true,
        })
    ]

webpack插件列表: https://www.webpackjs.com/plugins/

devServer

webpack-dev-server - 创建一个本地服务,并能设置代理服务,并且能够实时重新加载

一、安装webpack-dev-server

$ npm i --save-dev webpack-dev-server

二、创建文件

// 创建项目目录
$ mkdir webpack_base_demo && cd webpack_base_demo      

// 创建配置文件
$ touch README.md  .gitignore  .babelrc  webpack.config.js

// 创建package.json
$ npm init 

// 配置.babelrc文件
{
    "presets": ["react", "env"],
    "env": {
        "development": {
        <!-- "plugins": [["react-transform", {
            "transforms": [{
                "transform": "react-transform-hmr",
                "imports": ["react"],
                "locals": ["module"]
            }]
        }]] -->
        }
    }
}

三、安装需要的loader插件

// 如果使用react框架来做项目,先下载包
    $ npm i --save react react-dom

// babel的插件,在react热更新
    $ npm i --save babel-plugin-react-transform react-transform-hmr   

// 使用Babel-loader来解析es6和react
    $ npm i --save babel-core babel-loader babel-preset-env babel-preset-react

    // vue-load - 解析和转换.vue文件,vue-template-compiler - 将vue-load提取出的HTML模板编译成可执行的JS代码,vue项目可直接安装vue-cli
    $ npm vue-load vue-template-compiler

    // jsx转换
    $ npm i --save jsx-loader

    // css模块化,可以在组件中引用指定模块的css文件, import './main.css'
    $ npm i --save style-loader css-loader 

    // 可以将js和css中的导入的图片替换成正确的地址,同时将文件输出到对应的位置
    $ npm i --save file-loader

    // 将文件的图片经过base64编码后注入js或css中
    $ npm i --save url-loader    

    // 加载SVG
    $ npm i --save svg-loader

    // CSS预处理器  autoprefixer 自动加载前缀
    $ npm i --save less-loader sass-loader

五、package.json配置

"scripts": {
    "dev": "webpack-dev-server --hot --inline --progress",
    "start": "webpack --progress --profile --colors --config webpack.config.js",
},
$ npm run start        // 启动开发环境

六、创建生成和开发配置文件

webpack.config.js 开发环境所用配置文件
webpack.pub.config.js  生产环境所用配置文件

七、注意

1、启动两个侦听一个是webpack,一个是devServer,单独启devServer热更新不执行编译,暂没找到解决方法

  $ npm run build

  $ npm run dev

devServer的执行命令

webpack-dev-server - 在 localhost:8080 建立一个 Web 服务器

webpack-dev-server –devtool eval - 为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号

webpack-dev-server –progress - 显示合并代码进度

webpack-dev-server –colors - 命令行中显示颜色

webpack-dev-server –content-base build // webpack-dev-server服务会默认以当前目录伺服文件,如果设置了content-base的话,服务的根路径则为build目录

webpack-dev-server –inline 可以自动加上dev-server的管理代码,实现热更新

webpack-dev-server –hot 开启代码热替换,可以加上HotModuleReplacementPlugin

webpack-dev-server –port 3000 设置服务端口

webpack与gulp

gulp 是 task runner,Webpack 是 module bundler

webpack对多入口支持的不太好

gulp没有模块化的支持,需要与webpack结合

Source Map

启动时需要加 --devtool source-map 参数重启DevServer后刷新页面,在chrome开发者工具就可以调试源码

常用的处理g

一、css处理

    基本问题包括:

        预编译语言转换
        样式文件挂载方式选择
        代码优化(合并及压缩)
        去除或保留指定格式的注释
        资源定位路径的转换
        响应式布局单位转换【可选】
        模块化【可选】
        处理浏览器兼容【可选】

    1、style-loader - 将处理结束的CSS代码存储在js中,运行时嵌入&lt;style&gt;后挂载至html页面上

    2、css-loader - 加载器,使webpack可以识别css模块

    3、postcss-loader - 加载器,下一篇将详细描述

    4、sass-loader - 加载器,使webpack可以识别scss/sass文件,默认使用node-sass进行编译

    5、mini-css-extract-plugin - 提取单独的css文件插件,4.0版本启用的插件,替代原extract-text-webpack-plugin插件,将处理后的CSS代码提取为独立的CSS文件

    6、optimize-css-assets-webpack-plugin - 插件,实现CSS代码压缩

    7、autoprefixer - 自动化添加跨浏览器兼容前缀


二、Assets 资源(图片、json、xml)

    * 体积压缩
    * 雪碧图合并及引用修正
    * 资源的引用路径自动替换

    1、file-loader - 处理资源文件打包

    2、url-loader - 优化项目中对于资源的引用路径,并设定大小限制

    3、html-loader - html中的静态资源替换

    module: {
        rules: [
            {    
                test:/\.(jpg|png|svg|gif)/,    
                use:[{      
                    loader:'file-loader',      
                    options:{        
                        outputPath:'imgs/'
                    }
                }]
            },
            {    
                test:/\.(jpg|png|svg|gif)/,    
                use:[{      
                    loader:'url-loader',      
                    options:{        
                        limit: 8129,            // 限制图片转base64引用大小
                        fallback: 'file-loader',        // 大小limit的交给file-loader处理
                        ouputpath: 'imgs/'        // 指定输出路径
                    }
                }]
            }
        ]
    }


三、处理JS和splitChunk

    Js文件打包需求

    * 代码编译(TS或ES6代码的编译)
    * 脚本合并
    * 公共模块识别
    * 代码分割
    * 代码压缩混淆

    1、Babel转换ES6+

        webpack.config.js: 
            module: {    
                rules: [
                    {        
                        test: /\.js$/,        
                        exclude: /node_modules/,        
                        use: [
                            {             
                                loader: 'babel-loader'
                            }
                        ]
                    }
                ]
            },

        .bablerc: 
            {    
                "presets":[
                    [
                        "env",
                        {            
                            "targets":{                
                                "browsers":"last 2 versions"
                            }
                        }
                    ]
                ],    
                "plugins": [         
                    "babel-plugin-transform-runtime" 
                ]
            }

    2、脚本合并


    3、脚本分割

        为什么要分割,如果遇到比如使用Echarts第三方库或公用文件,这个时候我们不希望把它与业务一起合并到一个文件中,会使这个文件变得非常打,不利于加载


    4、代码混淆压缩

        UglifyJs


    5、splitChunks

        用于提取公用文件或第三方组件,4.0废弃了CommonsChunkPlugin插件,使用optimization.splitChunks和optimization.runtimeChunk来代替

        vendor 加载公用文件或第三方组件

        entry: {
            index: path.resolve(basePath, 'js/index.js'),
            list: path.resolve(basePath, 'js/list.js'),
            vendors:  path.resolve(basePath, 'js/common.js'),
        },

        // 使用optimization,与entry同级,不需要放到plugins内
        optimization: {
            splitChunks: {
                cacheGroups: {
                    commons: {
                        name: "vendors",
                        chunks: "initial",
                        minChunks: 2
                    }
                }
            }
        },

        plugins: [
            new HtmlWebpackPlugin({
                title: '首页', 
                template: path.resolve(basePath, 'index.html'),
                filename: path.resolve(buildPath, 'index.html'),
                chunks:['index', 'vendors'],            // 这里加vendors
                inject:'body',
            })
        ]

        <!-- module.exports = { 
            optimization: {    
                splitChunks: {      
                    chunks: 'async',                        // 默认只作用于异步模块,为`all`时对所有模块生效,`initial`对同步模块有效
                    minSize: 30000,                            // 合并前模块文件的体积
                    minChunks: 1,                                // 最少被引用次数
                    maxAsyncRequests: 5,      
                    maxInitialRequests: 3,      
                    automaticNameDelimiter: '~',        // 自动命名连接符
                    cacheGroups: {        
                        vendors: {          
                            test: /[\\/]node_modules[\\/]/,          
                            minChunks:1,                        // 敲黑板
                            priority: -10                        // 优先级更高
                        },        
                        default: {          
                            test: /[\\/]src[\\/]js[\\/]/
                            minChunks: 2,                        // 一般为非第三方公共模块
                            priority: -20,          
                            reuseExistingChunk: true
                        }
                    },      
                    runtimeChunk:{         
                         name:'manifest'
                    }
                }
            } -->

解决问题

1、devServer启动时不编译,分别侦听

2、js文件引用动态生成到html文档内

3、第三方插件或公用组件splitChunk

| https://doc.webpack-china.org/concepts/ webpack中文网 v3.10.0
| https://www.jianshu.com/p/42e11515c10f
| http://webpack.wuhaolin.cn/ // book
| https://webpack.js.org/plugins/ // 自带插件
| https://zhuanlan.zhihu.com/p/32148338
| https://blog.csdn.net/keliyxyz/article/details/51571386
| http://react-china.org/t/webpack-output-filename-output-chunkfilename/2256/2 // output.filename 和output.chunkFilename
| http://www.alloyteam.com/2016/02/code-split-by-routes/ 按需加载
|
| 插件
| http://www.cnblogs.com/haogj/p/5160821.html // html-webpack-plugin html多页面构建
|
| 热更新
| https://github.com/gaearon/react-hot-loader // react
| https://github.com/vuejs/vue-loader // vue