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’]
     }
    }
  • 相关阅读:
    AutoFac中常用方法说明
    DI之循环依赖
    NB/T 10215-2019 风力发电机组 测风传感器等最新能源行业标准
    DL/T 691-2019等最新电力行业标准
    TSG D7006-2020 压力管道监督检验规则
    YY/T 0595-2020 医疗器械 质量管理体系YY/T 0287-2017 应用指南
    GB/T 38775-2020系列电动汽车无线充电系统标准
    最新电动汽车安全标准
    GB 38032-2020 电动客车安全要求
    GB 38031-2020 电动汽车用动力蓄电池安全要求
  • 原文地址:https://www.cnblogs.com/kidsitcn/p/8643575.html
Copyright © 2011-2022 走看看