zoukankan      html  css  js  c++  java
  • webpack-易混淆部分的解释

    原文链接:

    https://medium.com/@rajaraodv/webpack-the-confusing-parts-58712f8fcad9

    webpack的核心哲学

    1. 任何皆模块

    正如js文件可以是"modules",任何其他的文件,比如css, images, html都可以被视为modules。也就是说,你可以通过require("myJSfile.js")来加载js文件,也可以通过require("mycssFile.css")加载css文件。这也就意味着我们可以将任何工作成果视为更小的可管理的构建,可用于重用。

    2. 仅仅在你需要使用的时候,仅仅加载你需要的asset. 典型的,打包器接收所有的模块输入而最终生成以恶搞巨大的单个"bundle.js"文件.但是很多真实的应用,这个bundel.js文件可能会达到10MB-15MB的大小!因此,这种情况下会导致加载非常慢。webpack为了处理这种bundle过大的问题,webpack提供了几个好用的功能用于split你的代码,并且产生出多个"bundle" files,并且可以async异步地加载parts of the app,以便仅仅加载你当前需要的部分。

    下面我们来一个个探讨容易搞不清楚的webpack topic

    Development vs production

    首先我们要铭记在心的是webpack有非常朵的好功能,而这些功能中很大一部分仅仅是为"development-only"的功能,而一部分是"production-only"的,而剩下的部分是既可用于开发环境,又可用于生产环境。

    典型地,大多数项目通过使用两个大的webpack config file来分别处理dev和prod两种场景。

    要创建bundle,你可能会在package.json中这样写:

    "scripts":{
    // npm run build to build production bundles
    "build": "webpack --config webpack.config.prod.js",
    // npm run dev to generate development bundles and run dev server
    "dev": "webpack-dev-server"
    }

    webpack CLI vs webpack-dev-server

    webpack,作为打包工具,提供以下两个接口,理解这一点非常重要:

    1. webpack cli tool---这是默认的接口(随着webpack的安装而存在于.bin目录中)

    2. webpack-dev-server tool ---一个node.js server(你需要单独安装它)

    webpack CLI(非常适合做prodcution build)

    这个命令行工具通过cli接收一些配置option,或者通过一个config file来接收这些option(默认为webpack.config.js配置文件),这些配置选项将用于webpack的打包过程。

    虽然你可能是通过使用cli来开始学习webpack的,但是实际上命令行工具往往更多用于创建生产环境下使用的bundle.

    用法:

    OPTION 1: 
    //Install it globally
    npm install webpack --g
    //Use it at the terminal 
    $ webpack //<--Generates bundle using webpack.config.js
    
    OPTION 2 :
    //Install it locally & add it to package.json
    npm install webpack --save
    //Add it to package.json's script 
    “scripts”: {
     “build”: “webpack --config webpack.config.prod.js -p”,
     ...
     }
    //Use it by running the following:
    "npm run build"

    webpack-dev-server(非常适合创建开发的build,并serve静态的assets)

    webpack-dev-server是一个运行于8080端口的expresss nodejs server.这个server会自己调用webpack本身实现构建,并且server构建出来的bundle.这个server的好处是它可以提供比如"Live Reloading"或者"Hot Module Replacement(HMR)"的实用功能。

    npm install webpack-dev-server --save
    //Use it at the terminal
    $ webpack-dev-server --inline --hot
    OPTION 2:
    // Add it to package.json's script 
    
    “scripts”: {
     “start”: “webpack-dev-server --inline --hot”,
     ...
     }
    // Use it by running 
    $ npm start
    Open browser at:
    http://localhost:8080

    webpack vs webpack-dev-server options

    需要说明的是,比如"inline"或者"hot"这些配置选项仅仅是对webpack-dev-server来适用的。而比如"hide-modules"仅仅针对webpack cli来说是适用的。

    webpack-dev-server CLI options vs config options

    另外需要说明的一点是:你可以通过以下两种方式来传入webpack-dev-server配置选项options:

    1. 通过webpack.config.js的"devServer对象

    2.通过webpack-dev-server的CLI options传入:

    //Via CLI
    webpack-dev-server --hot --inline
    //Via webpack.config.js
    devServer: {
     inline: true,
     hot:true
     }

    我在测试中发现,有时通过devServer配置选项传入参数(hot:true, inline:true)并不总是能够工作,所以,我更喜欢通过在package.json中的cli option来传入对应的参数:

    //package.json
    {
    scripts: 
       {“start”: “webpack-dev-server --hot --inline”}
    }

    "hot" vs "inline" webpack-dev-server options:

     "inline"选项使得针对整个页面实现"live reloading"成为可能。"hot"选项使能了"hot module reloading"功能,而这个功能可以仅仅reload那些被变更过的component(而不是整个页面重新加载).如果我们同时传入两个配置选项,那么当source变化时,webpack-dev-server将会首先试图做HRM,如果HMR不work,则会reload整个页面。

    //When the source changes, all 3 options generates new bundle but,
     
    //1. doesn't reload the browser page
    $ webpack-dev-server
    //2. reloads the entire browser page
    $ webpack-dev-server --inline
    //3. reloads just the module(HMR), or the entire page if HMR fails
    $ webpack-dev-server  --inline --hot

     "entry" --String Vs Array Vs Object

    Entry这个配置项告诉webpack应用的root module或者starting point在哪里。这个配置项可以是string,可以是array,也可以是object.这个灵活性可能让我们搞得糊涂,但是这些不同类型的数据实际上是用于不同的目的的。

    如果你有一个single starting point的话,那么string, array, object都是一样的结果。

    entry-array

    但是,如果你想追加多个互不依赖的文件,那么可以使用array格式

    比如,你可能需要"googleAnalytics.js"到你的html中,那么你可以告诉webpack追加该analytics.js到bundle.js的后面:

    entry-object

    如果你有一个多页的web应用,有多个html文件(index.html, profile.html等),而不是一个SPA w/ multi-views, 

    那么你可以通过entry object告诉webpack需要一次性创建多个bundles。

    下面的配置将产生两个js bundle文件:indexEntry.js和profileEntry.js分别应用于index.html和profile.html中

    使用方法为:

    //profile.html
    <script src=”dist/profileEntry.js”></script>
    //index.html
    <script src=”dist/indexEntry.js”></script>

    entry-combination

    你也可以在object entry里面使用array entries。例如,下面的config将产生3个文件:vendor.js和index.js, profile.js:

    output-"path" vs "publicPath"

    output告诉webpack我们将最终的输出存放在哪里一级如何存放。这里两个参数:path和publicPath可能会产生歧义和误解。

    "path"告诉webpack我们将最终的bundle存放在哪里。耳"publicPath"则被多个webpack plugin来使用用于当产生production build时更新在html,css文件中的url

     

    例如,在你的css中,你可能有一个url从你的localhost来load './test.png‘。但是在生产环境下,test.png文件可能存在于CDN中。这意味着你可能需要手工的更新这些url以便在生产环境中可以指向到正确的url地址。

    为了解决这个手工修改url的问题,你可以使用webpack的publicPath参数,而这个参数对几乎所有的plugin都是能够理解并使用这个publicPath参数的,并且自动在创建production build时更新这些url.

    // Development: Both Server and the image are on localhost
    .image { 
      background-image: url(‘./test.png’);
     }
    // Production: Server is on Heroku but the image is on a CDN
    .image { 
      background-image: url(‘https://someCDN/test.png’);
     }

    loaders and chaning loaders

    loaders是一些额外的node modules专门用于帮助'load'或者'import'各种类型的文件到浏览器可以认识的js, css文件格式。更进一步,loader也允许通过require或者import来import这些文件到js中。 

     例如:你可以使用bable-loader来转换es6写的js代码到浏览器可以认识的es5 javascript:

    module: {
     loaders: [{
      test: /.js$/, ←Test for ".js" file, if it passes, use the loader
      exclude: /node_modules/, ←Exclude node_modules folder
      loader: ‘babel’ ←use babel (short for ‘babel-loader’)
     }]

     chaining loaders(从右往左)

    多个loaders可以级联起来,针对同一个文件做不同的转换。级联是从右往左工作的,同时使用" ! "来隔离

    例如,我们如果有一个"mycssfile.css"文件,我们需要将它的内容dump到html的<style>css content</style>中。我们可以通过以下两个loaders来实现这个功能:css-loader和style-loader

    module: {
     loaders: [{
      test: /.css$/,
      loader: ‘style!css’ <--(short for style-loader!css-loader)
     }]

    下面这张图可以解释这个过程是如何工作的:

    1. 首先webpack在module中检索相关依赖,webpack看到mycssfile.css通过require来做import,因此mycssfile.css将作为dependency来处理,webpack首先将该css文件给到'css-loader'来做处理

    2. css-loader加载所有的css内容以及该css内容中自己的depency(比如@import othercss),并保存为json. webpack然后将这个结果传给style-loader继续处理。

    3. style-loader则接收这个json,并且增加<style>css contents</style>并将这个字符串插入到index.html文件中

    loaders Themselves can be configured

    loaders可以通过传入不同的parameters以不同的方式来工作。

    在下面的例子中,我们配置url-loader当image小于1024字节的话直接使用DataURLs。我们可以传入limit参数来指定这个大小。

    .babelrc文件

    babel-laoder使用"presets"配置选项使能如何转换es6为es5的过程,一级如何解析react’s jsx 到js文件。我们可以通过query参数传入配置:

    module: {
      loaders: [
        {
          test: /.jsx?$/,
          exclude: /(node_modules|bower_components)/,
          loader: 'babel',
          query: {
            presets: ['react', 'es2015']
          }
        }
      ]
    }

    然而,很多项目中babel的配置项目可能很多,这种情况下,你就可以把balble的这些配置项目放到.babelrc文件中去。babel-loader将自动加载这个.babelrc文件如果它存在的话。

    所以在很多例子中,你可能会看到:

    //webpack.config.js 
    module: {
      loaders: [
        {
          test: /.jsx?$/,
          exclude: /(node_modules|bower_components)/,
          loader: 'babel'
        }
      ]
    }
    
    //.bablerc
    {
     “presets”: [“react”, “es2015”]
    }

    Plugins

    plugins是一些针对输出的bundle执行特别的工作的node modules.

    例如,uglifyJSPlugin的作用是接收bundle.js作为输入并且混淆最小化该文件以减少文件的体积。

    类似地,extract-text-webpack-plugin这个plugin则内部通过使用css-loader,style-loader来收集所有css内容并整合到一处并最终抽出这些css内容到一个单一的style.css文件中,并且在index.html中产生一个指向该style.css的link。

    //webpack.config.js
    //Take all the .css files, combine their contents and it extract them to a single "styles.css"
    var ETP = require("extract-text-webpack-plugin");
    
    module: {
     loaders: [
      {test: /.css$/, loader:ETP.extract("style-loader","css-loader") }
      ]
    },
    plugins: [
        new ExtractTextPlugin("styles.css") //Extract to styles.css file
      ]
    }

    需要说明的是,如果你想在html中inline使用这些css样式,你可以不使用该plugin,而仅仅通过使用css, style loaders达到目的:

    module: {
     loaders: [{
      test: /.css$/,
      loader: ‘style!css’ <--(short for style-loader!css-loader)
     }]

    loaders vs plugins

    loaders仅在bundle生成过程中或者生成之前针对单个的文件做转换。

    而plugin则在bundle创建的结束之后针对整个bundle或者chunk level执行操作。一些像commonsChunksPlugin的插件则更进一步会修正bundles本身是如何创建的过程。

    resolving file extensions

    很多webpack config文件有一个resolve extensions属性,并有一个空字符串作为值。

    这个空字符串用于帮助resolve imports without extensions,比如require("./myJSFile")或者import myJSFile从"./myJSFile”而不用加上文件的扩展名.

    {
     resolve: {
       extensions: [‘’, ‘.js’, ‘.jsx’]
     }
    }
  • 相关阅读:
    Treap 树堆 容易实现的平衡树
    (转)Maven实战(二)构建简单Maven项目
    (转)Maven实战(一)安装与配置
    根据请求头跳转判断Android&iOS
    (转)苹果消息推送服务器 php 证书生成
    (转)How to renew your Apple Push Notification Push SSL Certificate
    (转)How to build an Apple Push Notification provider server (tutorial)
    (转)pem, cer, p12 and the pains of iOS Push Notifications encryption
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 2/2
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 1/2
  • 原文地址:https://www.cnblogs.com/kidsitcn/p/8643575.html
Copyright © 2011-2022 走看看