zoukankan      html  css  js  c++  java
  • webpack总结

    一、Webpack 是什么?

    webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。 简单说就是模块加载器,通过使用Webpack,能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。

    二、为什么需要打包?

    • 像sass,JSX等代码虽然极大的提高了开发效率,但是本身并不被浏览器所识别,需要我们对其进行编译和打包,变成浏览器识别的代码

    • 模块化(让我们可以把复杂的代码细化为小的文件)

    • 优化加载速度(压缩和合并代码来提高加载速度,压缩可以减少文件体积,代码合并可以减少http请求)

    • 使用新的开发模式

    三、webpack主要特性

    • 同时支持CommonJS和AMD模块(对于新项目,推荐直接使用CommonJS);

    • 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持;

    • 可以基于配置或者智能分析打包成多个文件,实现公共模块或者按需加载;

    • 支持对CSS,图片等资源进行打包,从而无需借助Grunt或Gulp(browserify只能打包JS文件);

    • 开发时在内存中完成打包,性能更快,完全可以支持开发过程的实时打包需求;

    • source map有很好的支持。

    四、配置(webpack.config.js文件)

    var webpack = require('webpack');
    var path = require('path');
    var SpritesmithPlugin = require('webpack-spritesmith');
    module.exports = {
        // context: __dirname + '\app', //上下文
        entry: path.resolve(__dirname, 'app/index.js'), //入口文件
        output: { //输出文件
            path: path.resolve(__dirname, 'app/build/script'),
            filename: 'bundle.js'
        },
        module: {
            loaders: [ //加载器
                {test: /.html$/, loader: 'raw'},
                // {test: /.css$/, loader: 'style!css!postcss'},
                {test: /.css$/, loader: 'style!css'},
                // {test: /.(png|jpg|ttf)$/, loader: 'url?limit=8192'}
                {test: /.(png|jpg|ttf)$/, loader: 'file!url?limit=8192'}
            ]
        },
        // postcss: function () {
        // return [autoprefixer];
        // },
        plugins: [ //插件
            new webpack.BannerPlugin('This file is created by shiddong.'),
            new SpritesmithPlugin({
                src: {
                    cwd: path.resolve(__dirname, 'app/images/'),
                    glob: '*.png'
                },
                target: {
                   image: path.resolve(__dirname, 'app/build/images/sprite.png'),
                   css: path.resolve(__dirname, 'app/build/css/sprite.css') //产生的样式文件,图片的样式类名是 icon-图片名
                },
               apiOptions: {
                   cssImageRef: '../images/sprite.png'
               },
               spritesmithOptions: {
                   algorithm: 'top-down'
               }
           })
        ]
    };

    五、webpack.config.js 配置详解

    (1)entry

    入口文件,可以传字符串,那说明入口文件只有一个;也可以传数组或对象,指定多个入口文件。

    有两种语法:

    <1> 先require path,再利用reslove方法对路径进行解析。

    var path = require('path');
    entry: path.resolve(__dirname, 'app/index.js'), //入口文件

    <2> 先定义好上下文路径,那么entry中的路径直接在这个路径下开始

    context: __dirname + '\app', //上下文
    entry: './index.js', //入口文件

    注:webpack中引入的path是nodejs内置的package,用来处理路径 —— 参考菜鸟教程node.js工具模块。

    当entry是数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器,webpack-dev-server。webpack-dev-server会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:

    entry: [
        'webpack/hot/only-dev-server',
        './js/app.js'
    ]

    当entry是个对象的时候,我们可以将不同的文件构建成不同的文件,按需使用。每一个键值对,就是一个入口文件。

    备注:当然也有其他的办法,如express框架,在index.html同路径建立一个server.js,然后运行 node server.js即可。

    // express 是一个基于Node.js 平台的web应用开发框架 —— 快速、极简、开放
    var port = 8000,
    express = require('express'),
    app = express();
    app.use('/', express.static(__dirname));
    app.listen(port);
    console.log('Now serving http://localhost:' + port + '/index.html');

    (2)output

    生成打包文件的配置,可以指定path(路径),当有多个入口文件时,还可以使用[name]、[hash]、[chunkhash]等值,来对应替换为入口的文件的配置。

    output: { //输出构建后的文件
        path: path.resolve(__dirname, 'app/build/script'),
        filename: 'bundle.js'
    }


    当entry中定义构建多个文件时,filename可以对应的更改为[name].js用于定义不同文件构建后的名字。

    entry: {
        index: 'index.js'
    },
    output: {
        path: './js',
        filename: '[name].bundle.js' // [name] 会由entry中的键(这里是index)替换
    }

    (3)module

    定义了对模块的处理逻辑,在webpack中,所有的资源都被当做模块。对于不同文件类型的资源,都有对应的loader。
    模块的加载相关配置定义在module.loaders中。


    loaders: 加载器配置,通过正则表达式去匹配不同后缀的文件名,然后给它们定义不同的加载器。它可以转换项目中的资源文件,比如说给css文件定义串联的两个加载器(!用来定义级联关系),顺序是从右向左使用:

    module: {
        loaders: [
            { test: /.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /.js$/, exclude: /node_modules/, loader: 'babel-loader'},
            { test: /.css$/, loader: "style!css" },
            { test: /.less/, loader: 'style-loader!css-loader!less-loader'}
        ]
    }


    其中,exclude: /node_modules/,
    exclude,include手动添加屏蔽不需要处理的文件(文件夹)或必须处理的文件(文件夹)

    比较常用的loader:

    css-loader: 将样式打包成字符串。
    style-loader:将样式字符串添加到页面的style标签中 

    还可以添加用来定义png、jpg这样的图片资源在大于8k时正常打包,小于8k时自动处理为base64图片的加载器:

    { test: /.(png|jpg)$/,loader: 'url-loader?limit=8192'}

    其中,? 表示加载器支持通过查询字符串的方式接受参数。

    给css和less还有图片添加了loader之后,我们不仅可以像在node中那样require js文件了,我们还可以require css、less甚至图片文件:

    require('./bootstrap.css');
    require('./myapp.less');
    var img = document.createElement('img');
    img.src = require('./glyph.png');

    这样require来的文件会内联到 js bundle中。如果我们需要保留require的写法又想把css文件单独拿出来,可以使用[extract-text-webpack-plugin]插件。

    (4)plugins

    插件,它可以干很多很多的事情,非常强大,官方提供了很多插件,第三方也可以写插件。对于用到的插件,只需要将插件new出来放到数组中即可。

    <1> BannerPlugin 内置插件来实践插件的配置和运行,这个插件的作用是给输出的文件头部添加注释信息。
    <2> ProvidePlugin 插件的作用是自动加载jquery模块,也就是说将jquery变成了全局的模块,当然我们需要在index.html中使用script标签导入。


    [原因:由于jquery没有模块化的概念,也没有适配webpack,所以我们使用jquery时,需要在index.html中导入,然后使用 ProvidePlugin 插件使其自动加载。]

    plugins: [
        new webpack.BannerPlugin('This file is created by shiddong.'),
        // 此插件会自动加载jquery,解决jquery无法引用的问题
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery",
            window.jQuery: "jquery"
        })
    ]

    (5)导入使用

    只需要在index.html中导入bundle.js,<script src="bundle.js">script>,不需要在index.html中导入js文件了,只需要使用 require 导入模块就行,webpack会自己解决它们之间的依赖。

    <1> 依赖第三方库可以将其下载到node-modules中,然后导入相应的模块:

    //require('angular')导入的是 node_modules 中的angular模块
    require("angular"); //var angular = require('angular');
    require("bootstrap");
    var demoApp = angular.module('demoApp', []);

    <2> 或者类似于导入本地的js文件,可以建立一个 common.js 文件,然后导入 angular 和 bootstrap。然后在使用的时候直接require('./common')

    (6)处理图片

    loaders: [
        {
          test: /.(png|jpg)$/,
          loader: 'url-loader?limit=8192'
        }
      ]

    其中,

    <1> test 属性代表可以匹配的图片类型,除了 png、jpg 之外也可以添加 gif 等,以竖线隔开即开。
    <2> loader 后面 limit 字段代表图片打包限制,这个限制并不是说超过了就不能打包,而是指当图片大小小于限制时会自动转成 base64 码引用。上例中大于8192字节的图片正常打包,小于8192字节的图片以 base64 的方式引用。

    //Option 1,使用 ?
    { test: /.png$/,
       loader: 'url-loader?limit=1024'
    }
    //Option 2,使用query属性
    { test: /.png$/,
      loader: 'url-loader',
      query: {limit=1024}
    }

    <3> url-loader 后面除了 limit 字段,还可以通过 name 字段来指定图片打包的目录与文件名:

    loaders: [
        {
          test: /.(png|jpg)$/,
          loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
        }
      ]

    name 字段指定了在打包根目录(output.path)下生成名为 images 的文件夹,并在原图片名前加上8位 hash 值。

    (7)生成雪碧图

    var path = require('path');
    var SpritesmithPlugin = require('webpack-spritesmith'); //安装雪碧图依赖模块:webpack-spritesmith
    module.exports = {
        entry: path.resolve(__dirname, 'app/main.js'),
        output: {
            path: path.resolve(__dirname, 'build'),
            filename: 'bundle.js'
        },
        plugins: [
            new SpritesmithPlugin({
                src: {
                    cwd: path.resolve(__dirname, 'app/images/'),
                    glob: '*.png'
                },
                target: {
                    image: path.resolve(__dirname, 'build/images/sprite.png'),
                    css: path.resolve(__dirname, 'build/css/sprite.css') //产生的样式文件,图片的样式类名是 icon-图片名
                },
                apiOptions: {
                    cssImageRef: '../images/sprite.png'
                },
                spritesmithOptions: {
                    algorithm: 'top-down'
                }
            })
        ]
    };

    链接:https://zhuanlan.zhihu.com/p/23873229


    其他:

    (8)resolve

    定义解析模块路径时的配置,最常用的就是extensions,可以用来指定模块的后缀,这样在引入模块是就不需要写后缀了,会自动补全。
    webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:

    resolve:{
        extensions:['', '.js', '.json']
    }

    然后我们想要加载一个js文件时,只要require('common')就可以加载common.js文件了。

    (9)externals

    当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:

    externals: {
        "jquery": "jQuery"
    }

    这样我们就可以放心的在项目中使用这些API了:var jQuery = require(“jquery”);

    (10)context

    当我们在require一个模块的时候,如果在require中包含变量,像这样:

    require("./mods/" + name + ".js");

    那么在编译的时候我们是不能知道具体的模块的。但这个时候,webpack也会为我们做些分析工作:
        1.分析目录:'./mods';
        2.提取正则表达式:'/^.*.js$/';


    于是这个时候为了更好地配合webpack进行编译,我们可以给它指明路径,像在cake-webpack-config中所做的那样(我们在这里先忽略abcoption的作用):

    var currentBase = process.cwd();
    var context = abcOptions.options.context ? abcOptions.options.context :
    path.isAbsolute(entryDir) ? entryDir : path.join(currentBase, entryDir);

    六、按需加载

    传统的模块打包工具(module bundlers)最终将所有的模块编译生成一个庞大的bundle.js文件。但是在真实的app里边,“bundle.js”文件可能有10M到15M之大可能会导致应用一直处于加载中状态。因此Webpack使用许多特性来分割代码然后生成多个“bundle”文件,而且异步加载部分代码以实现按需加载。

    七、执行打包

    如果通过npm install -g webpack方式安装webpack的话,可以通过命令行直接执行打包命令,比如:
    $ webpack –config webpack.config.js
    这样就会读取当前目录下的webpack.config.js作为配置文件执行打包操作。默认查找webpack.config.js,所以我们在这里只需要执行webpack 命令即可。

    八、常用webpack命令

    在开发环境构建一次
    webpack
    构建并生成源代码映射文件
    webpack -d
    在生成环境构建,压缩、混淆代码,并移除无用代码
    webpack -p
    快速增量构建,可以和其他选项一起使用
    webpack –watch
    progress 显示打包过程中的进度,colors打包信息带有颜色显示
    webpack –progress –colors

    九、理解文件路径

    require(‘lodash’) // 从模块目录查找
    require(‘./file’) // 按相对路径查找
    CSS 及图片的引用
    require(‘./bootstrap.css’);
    require(‘./myapp.less’);
    var img = document.createElement(‘img’);
    img.src = require(‘./weibo.png’);

    十、其他插件功能

    OccurenceOrderPlugin:给经常使用的模块分配最小长度的id,这样可以减少文件大小。
    HotModuleReplacementPlugin:是热替换,热替换和dev-server的hot有什么区别?不用刷新页面,可用于生产环境。
    NoErrorsPlugin:在打包时不会因为错误而中断
    ProvidePlugin: 定义一些在import时能自动引入的变量,如定义了 $: 'jquery' 后,可以在文件中直接使用$,webpack可以自动帮你加上 var $ = require('jquery')。
    DllPlugin: 将一些模块预编译,类似windows里的dll,可以在项目中直接使用,无需再构建。注意要在output中指定 library ,并在DllPlugin中指定与其一致的 name ,在有多个入口时可以使用 [name] 和 [hash] 来区分,因为这个参数是要赋值到global上的,所以这里使用 [hash] 不容易出现变量名冲突的情况。
    DllReferencePlugin: 引用之前打包好的dll文件,注意下context参数,这个应该根据manifest.json文件中的引用情况来赋值,如果引用的都是npm安装的库,这里就填项目根目录就好了。
    DefinePlugin: 可以定义编译时的全局变量,有很多库(React, Vue等)会根据 NODE_ENV 这个变量来判断当前环境。为了尽可能减少包大小,在生产环境中要定义其为 JSON.stringify(“production”)
    optimize.UglifyJsPlugin: 配置压缩代码。
    optimize.DedupePlugin: 可以减少重复文件数。
    ExtractTextPlugin: 可以将所有css文件打包到一个css文件中。

    十一、参考资料

    1、webpack参考链接 
    http://webpackdoc.com

    2、Webpack入门(其文章底部有些链接可以参考)———— 基本概念、webpack.config.js配置详解
    http://blog.csdn.net/liujie19901217/article/details/51026943

    3、入门 Webpack,看这篇就够了(很好,工作方式对比清晰、参数的表格清晰)******
    https://segmentfault.com/a/1190000006178770#articleHeader8

    4、[译] 通过 Webpack 实现 AngularJS 的延迟加载  ******
    https://toutiao.io/posts/46gvgm/preview

    5、30分钟手把手教你学webpack实战(内容比较全面、详细)******
    http://www.cnblogs.com/tugenhua0707/p/4793265.html

    6、Webpack + Angular的组件化实践
    https://segmentfault.com/a/1190000003915443

    7、为何webpack风靡全球?三大主流模块打包工具对比
    http://www.techug.com/webpack-requirejs-browserify

    webpack: code spliting / loader/plugin

    8、前端构建工具漫谈,fis3、webpack、rollup.js 
    https://zhuanlan.zhihu.com/p/20933749

    9、轻松入门webpack——官方文档解读
    http://shuaihua.cc/article/webpack/webpack.php

    10、关于雪碧图的详细介绍
    https://zhuanlan.zhihu.com/p/23873229?utm_source=tuicool&utm_medium=referral

    11、boi剖析 - 基于webpack的css sprites实现方案
    http://www.cnblogs.com/ihardcoder/p/6053231.html

  • 相关阅读:
    requireJS搭建
    html启动本地.exe文件
    自定义input[type="checkbox"]的样式
    使用rem单位时css sprites的坑
    visibility API
    css动画
    去除ios端输入框的弹出
    *java类的生命周期
    处理高并发,防止库存超卖
    java注解的使用
  • 原文地址:https://www.cnblogs.com/shih/p/6826875.html
Copyright © 2011-2022 走看看