webpack 原理 抽离公共代码_webpack3 抽离js公共代码 - CSDN
精华内容
参与话题
  • webpack提取公共模块-CommonsChunkPlugin

    千次阅读 2018-04-02 10:53:28
    CommonsChunkPlugin官方文档解释: CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又...这个带来速度上的提升,因为浏览器会迅速将公共代码从缓存中取出来,而不是每次访问一个新页面时,再去加...

    CommonsChunkPlugin官方文档解释:

    CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

    而在实际项目中,本人是这样的应用的,项目结构如下图:
    这里写图片描述

    其中的indexlogin用到了 m1.js,m2.js的方法,代码如下:

    import {xiaoyu} from '../m1.js'
    import {dayu} from '../m2.js'

    webpack.config.js是这么配置的:

    entry:{
        'index':['./src/page/index/index.js'],
        'login':['./src/page/login/index.js']
      },
     output:{
        path:path.resolve(__dirname, 'dist'),
        filename:'js/[name].js'
      },

    所以最后打包,会在./dist/下面分别打包出index.js和login.js, 看了一下打包后的文件。
    毫无意外,这两个文件里面都打包了 m1.js,m2.js的方法,
    其实完全可以把 m1.js,m2.js单独提取出来合成一个文件引入到需要的页面上去,这样就不用重复的打包了,这个时候就用到CommonsChunkPlugin这个插件

    webpack.config.js配置如下

    plugins:[
        new webpack.optimize.CommonsChunkPlugin({
          name : 'common',
          filename : 'js/base.js'
        })
      ]

    加入后再重新打包

    会发现 dist下面的js文件夹下面会多出一个base.js的打包文件,里面就是把 m1.js,m2.js单独拿了出来重新打包成了一个文件,大大的节省了空间
    只需要在主文件下面引入base.js就可以了


    还有一个问题就是

    m1.js,m2.js是我分别在用到的时候 import引入进来的,如果有一个文件存放的就是共用方法,那我难道要把这个文件import引入到所有的文件里面去吗?
    这个问题CommonsChunkPlugin也是能解决的:

    首先需求如下图

    这里写图片描述

    在common下面的文件是我的公用方法,那么我可以把common下的方法一同打包到base.js,这样就直接一个文件全局引用了

    webpack.config.js配置如下

    entry:{//首先在入口引入公共文件,取名'common'
        'commom':['./src/page/common/index.js']
        'index':['./src/page/index/index.js'],
        'login':['./src/page/login/index.js']
      },
      output:{
        path:path.resolve(__dirname, 'dist'),
        filename:'js/[name].js'
      },
      plugins:[
        new webpack.optimize.CommonsChunkPlugin({
          name : 'common',//这里的'common'回去找上面入口处引入的common
          filename : 'js/base.js'
        })
      ]

    最后,在这里记录一个使用CommonsChunkPlugin时的坑
    打包时报错webpackJsonp is not defined
    其实就是你打包的公共模块 base.js并没有引用,引用时必须放在打包的其他的js文件的上面

    展开全文
  • webpack的面试题总结

    千次阅读 2019-07-25 20:53:51
    随着现代前端开发的复杂度和规模越来越庞大,已经不能抛开工程化来独立开发了,如react的jsx代码必须编译后才能在浏览器中使用;又如sass和less的代码...在众多前端工程化工具中,webpack脱颖而出成为了当今最...

    本文转自于前端面试总结@知乎专栏:https://zhuanlan.zhihu.com/p/44438844

    随着现代前端开发的复杂度和规模越来越庞大,已经不能抛开工程化来独立开发了,如react的jsx代码必须编译后才能在浏览器中使用;又如sass和less的代码浏览器也是不支持的。 而如果摒弃了这些开发框架,那么开发的效率将大幅下降。在众多前端工程化工具中,webpack脱颖而出成为了当今最流行的前端构建工具。 然而大多数的使用者都只是单纯的会使用,而并不知道其深层的原理。希望通过以下的面试题总结可以帮助大家温故知新、查缺补漏,知其然而又知其所以然。

     

    问题列表

    1. webpack与grunt、gulp的不同?
    2. 与webpack类似的工具还有哪些?谈谈你为什么最终选择(或放弃)使用webpack?
    3. 有哪些常见的Loader?他们是解决什么问题的?
    4. 有哪些常见的Plugin?他们是解决什么问题的?
    5. Loader和Plugin的不同?
    6. webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全
    7. 是否写过Loader和Plugin?描述一下编写loader或plugin的思路?
    8. webpack的热更新是如何做到的?说明其原理?
    9. 如何利用webpack来优化前端性能?(提高性能和体验)
    10. 如何提高webpack的构建速度?
    11. 怎么配置单页应用?怎么配置多页应用?
    12. npm打包时需要注意哪些?如何利用webpack来更好的构建?
    13. 如何在vue项目中实现按需加载?

    1. webpack与grunt、gulp的不同?

    三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。

    gruntgulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。

    webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。

    所以总结一下:

    • 从构建思路来说
    gulp和grunt需要开发者将整个前端构建过程拆分成多个`Task`,并合理控制所有`Task`的调用关系
    webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工
    • 对于知识背景来说
      gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路

    2. 与webpack类似的工具还有哪些?谈谈你为什么最终选择(或放弃)使用webpack?

    同样是基于入口的打包工具还有以下几个主流的:

    从应用场景上来看:

    • webpack适用于大型复杂的前端站点构建
    • rollup适用于基础库的打包,如vue、react
    • parcel适用于简单的实验性项目,他可以满足低门槛的快速看到效果
    由于parcel在打包过程中给出的调试信息十分有限,所以一旦打包出错难以调试,所以不建议复杂的项目使用parcel

    3.有哪些常见的Loader?他们是解决什么问题的?

    • file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
    • url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
    • source-map-loader:加载额外的 Source Map 文件,以方便断点调试
    • image-loader:加载并且压缩图片文件
    • babel-loader:把 ES6 转换成 ES5
    • css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
    • style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
    • eslint-loader:通过 ESLint 检查 JavaScript 代码

    4.有哪些常见的Plugin?他们是解决什么问题的?

    • define-plugin:定义环境变量
    • commons-chunk-plugin:提取公共代码
    • uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码

    5.Loader和Plugin的不同?

    不同的作用

    • Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
    • Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

    不同的用法

    • Loadermodule.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options
    • Pluginplugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

    6.webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全

    Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

    1. 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
    2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
    3. 确定入口:根据配置中的 entry 找出所有的入口文件;
    4. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
    5. 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
    6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
    7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

    在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。


    7.是否写过Loader和Plugin?描述一下编写loader或plugin的思路?

    Loader像一个"翻译官"把读到的源文件内容转义成新的文件内容,并且每个Loader通过链式操作,将源文件一步步翻译成想要的样子。

    编写Loader时要遵循单一原则,每个Loader只做一种"转义"工作。 每个Loader的拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用this.callback()方法,将内容返回给webpack。 还可以通过 this.async()生成一个callback函数,再用这个callback将处理后的内容输出出去。 此外webpack还为开发者准备了开发loader的工具函数集——loader-utils

    相对于Loader而言,Plugin的编写就灵活了许多。 webpack在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。


    8.webpack的热更新是如何做到的?说明其原理?

    webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

    原理:

    图片来自饿了么前端@知乎专栏

    首先要知道server端和client端都做了处理工作

    1. 第一步,在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中。
    2. 第二步是 webpack-dev-server 和 webpack 之间的接口交互,而在这一步,主要是 dev-server 的中间件 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露的 API对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
    3. 第三步是 webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打包。当我们在配置文件中配置了devServer.watchContentBase 为 true 的时候,Server 会监听这些配置文件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload。注意,这儿是浏览器刷新,和 HMR 是两个概念。
    4. 第四步也是 webpack-dev-server 代码的工作,该步骤主要是通过 sockjs(webpack-dev-server 的依赖)在浏览器端和服务端之间建立一个 websocket 长连接,将 webpack 编译打包的各个阶段的状态信息告知浏览器端,同时也包括第三步中 Server 监听静态文件变化的信息。浏览器端根据这些 socket 消息进行不同的操作。当然服务端传递的最主要信息还是新模块的 hash 值,后面的步骤根据这一 hash 值来进行模块热替换。
    5. webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回给了 webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传给它的信息以及 dev-server 的配置决定是刷新浏览器呢还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那些步骤了。
    6. HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到上一步传递给他的新模块的 hash 值,它通过 JsonpMainTemplate.runtime 向 server 端发送 Ajax 请求,服务端返回一个 json,该 json 包含了所有要更新的模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp 请求,获取到最新的模块代码。这就是上图中 7、8、9 步骤。
    7. 而第 10 步是决定 HMR 成功与否的关键步骤,在该步骤中,HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。
    8. 最后一步,当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。

    9.如何利用webpack来优化前端性能?(提高性能和体验)

    用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。

    • 压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPluginParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
    • 利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径
    • 删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现
    • 提取公共代码。

    10.如何提高webpack的构建速度?

    1. 多入口情况下,使用CommonsChunkPlugin来提取公共代码
    2. 通过externals配置来提取常用库
    3. 利用DllPluginDllReferencePlugin预编译资源模块 通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过DllReferencePlugin将预编译的模块加载进来。
    4. 使用Happypack 实现多线程加速编译
    5. 使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。 原理上webpack-uglify-parallel采用了多核并行压缩来提升压缩速度
    6. 使用Tree-shakingScope Hoisting来剔除多余代码

    11.怎么配置单页应用?怎么配置多页应用?

    单页应用可以理解为webpack的标准模式,直接在entry中指定单页应用的入口即可,这里不再赘述

    多页应用的话,可以使用webpack的 AutoWebPlugin来完成简单自动化的构建,但是前提是项目的目录结构必须遵守他预设的规范。 多页应用中要注意的是:

    • 每个页面都有公共的代码,可以将这些代码抽离出来,避免重复的加载。比如,每个页面都引用了同一套css样式表
    • 随着业务的不断扩展,页面可能会不断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置

    12.npm打包时需要注意哪些?如何利用webpack来更好的构建?

    Npm是目前最大的 JavaScript 模块仓库,里面有来自全世界开发者上传的可复用模块。你可能只是JS模块的使用者,但是有些情况你也会去选择上传自己开发的模块。 关于NPM模块上传的方法可以去官网上进行学习,这里只讲解如何利用webpack来构建。

    NPM模块需要注意以下问题:

    1. 要支持CommonJS模块化规范,所以要求打包后的最后结果也遵守该规则。
    2. Npm模块使用者的环境是不确定的,很有可能并不支持ES6,所以打包的最后结果应该是采用ES5编写的。并且如果ES5是经过转换的,请最好连同SourceMap一同上传。
    3. Npm包大小应该是尽量小(有些仓库会限制包大小)
    4. 发布的模块不能将依赖的模块也一同打包,应该让用户选择性的去自行安装。这样可以避免模块应用者再次打包时出现底层模块被重复打包的情况。
    5. UI组件类的模块应该将依赖的其它资源文件,例如.css文件也需要包含在发布的模块里。

     

    基于以上需要注意的问题,我们可以对于webpack配置做以下扩展和优化:

    1. CommonJS模块化规范的解决方案: 设置output.libraryTarget='commonjs2'使输出的代码符合CommonJS2 模块化规范,以供给其它模块导入使用
    2. 输出ES5代码的解决方案:使用babel-loader把 ES6 代码转换成 ES5 的代码。再通过开启devtool: 'source-map'输出SourceMap以发布调试。
    3. Npm包大小尽量小的解决方案:Babel 在把 ES6 代码转换成 ES5 代码时会注入一些辅助函数,最终导致每个输出的文件中都包含这段辅助函数的代码,造成了代码的冗余。解决方法是修改.babelrc文件,为其加入transform-runtime插件
    4. 不能将依赖模块打包到NPM模块中的解决方案:使用externals配置项来告诉webpack哪些模块不需要打包。
    5. 对于依赖的资源文件打包的解决方案:通过css-loaderextract-text-webpack-plugin来实现,配置如下:
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    module.exports = {
      module: {
        rules: [
          {
            // 增加对 CSS 文件的支持
            test: /\.css/,
            // 提取出 Chunk 中的 CSS 代码到单独的文件中
            use: ExtractTextPlugin.extract({
              use: ['css-loader']
            }),
          },
        ]
      },
      plugins: [
        new ExtractTextPlugin({
          // 输出的 CSS 文件名称
          filename: 'index.css',
        }),
      ],
    };
    

    13.如何在vue项目中实现按需加载?

    Vue UI组件库的按需加载 为了快速开发前端项目,经常会引入现成的UI组件库如ElementUI、iView等,但是他们的体积和他们所提供的功能一样,是很庞大的。 而通常情况下,我们仅仅需要少量的几个组件就足够了,但是我们却将庞大的组件库打包到我们的源码中,造成了不必要的开销。

    不过很多组件库已经提供了现成的解决方案,如Element出品的babel-plugin-component和AntDesign出品的babel-plugin-import 安装以上插件后,在.babelrc配置中或babel-loader的参数中进行设置,即可实现组件按需加载了。

    {
      "presets": [["es2015", { "modules": false }]],
      "plugins": [
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    

    单页应用的按需加载 现在很多前端项目都是通过单页应用的方式开发的,但是随着业务的不断扩展,会面临一个严峻的问题——首次加载的代码量会越来越多,影响用户的体验。

    通过import(*)语句来控制加载时机,webpack内置了对于import(*)的解析,会将import(*)中引入的模块作为一个新的入口在生成一个chunk。 当代码执行到import(*)语句时,会去加载Chunk对应生成的文件。import()会返回一个Promise对象,所以为了让浏览器支持,需要事先注入Promise polyfill

    展开全文
  • webpack的介绍与使用

    万次阅读 热门讨论 2018-03-12 16:17:44
    前端打包工具有webpack、grunt、gulp等,这里主要介绍webpack.一、webpack的基本能力:处理依赖、模块化、打包 1、依赖管理:方便引用第三方模块,让模块更容易复用、避免全局注入导致的冲突、、避免重复加载或者...

    前端打包工具有webpack、grunt、gulp等,这里主要介绍webpack.

    一、webpack的基本能力:处理依赖、模块化、打包

         1、依赖管理:方便引用第三方模块,让模块更容易复用、避免全局注入导致的冲突、、避免重复加载或者加载不必要的模块

         2、合并代码:把各个分散的模块集中打包成大文件,减少HTTP的链接的请求次数,配合uglify.js可以减少、优化代码的体积

         3、各种插件:babel把ES6+转化为ES5-,eslint可以检查编译时的各种错误

    二、webpack的工作原理

          简单的说就是分析代码,找到“require”、“exports”、“define”等关键词,并替换成对应模块的引用。

          在一个配置文件中,指明对某些文件进行编译、压缩、组合等任务。把你的项目当成一个整体,通过一个给定的主文件              (index.js),webpack将从这个文件开始找到你的项目的所有的依赖文件,使用loaders处理他们,最后打包为一个浏览器可

          以识别的js文件。


    在没有使用webpack之前:

    举个例子:index.html里面有一大堆的css和js文件,如a.js   b.js     c.js等等

    (1)a.js要用到b.js里面的饿一个函数,则a.js要放在b.js后面

    (2)c.js要用到a.js里面的一个函数,则c.js要放在a.js后面

    (3)b.js又要用到某个js文件里面的函数,则b.js就要放在其后面

    如果有N多个js文件,需要手动处理他们的关系,即容易出错。


    使用webpack:

    webpack的理念就是一切皆模块化,把一堆的css文件和js文件放在一个总的入口文件,通过require引入,剩下的事情webpack会处理,包括所有模块的前后依赖关系,打包、压缩、合并成一个js文件,公共代码抽离成一个js文件、某些自己指定的js单独打包,模块可以是css/js/imsge/font等等。


    三、使用场景

    1、根据模板生成HTML,并自动处理上面的css/js引用路径

    2、自动处理<img>里面的图片路径,css里面背景图的路径,字体引用

    3、开启本地服务器,一边改写代码,一边自动更新页面内容

    4、编译jsx    es6     sass     less    coffescript等,并添加md5、sourcemap等辅助

    5、异步加载内容,不需要时不加载到DOM

    6、配合vue.js    react.js等框架开发


    四、使用webpack打包项目的操作流程

    准备条件:安装好npm和webpack

    node.js:下载路径,下载完之后安装,安装完之后在cmd面板输入  node   -v    出现版本号说明安装成功,输入  npm   -v出                    现版本号说明自带的npm也安装成功。

    webpack:使用npm全局安装webpack,在cmd面板输入   npm   install   -g   webpack

                      使用npm在项目中安装webpack,在项目路径下,在cmd面板中输入  npm   install   webpack    --save-dev

                      ( --save-dev表示开发时候依赖的东西,  --save是开发之后还依赖的东西 )


    下面详细介绍打包的整个过程

    1、在cmd中,执行npm init(目录是 D:\php_Study\WWW\webpack),如图所示

    如果没有需要修改的话可以一直按下enter键,直到出现yes/no,输入yes按下enter键,就会在文件夹webpack下生成配置文件package.json。如果要修改的话可以自己定义:

    name:项目名称

    version:项目版本号

    description:对这个项目的描述,或者描述使用webpack的那些功能

    entry point:入口文件名

    test command:测试时候的命令

    git repository:git上面的仓库名

    keywords:关键词

    author:作者名字

    license:许可证


    这一步完成之后,在webpack文件夹下的内容为:



    2、将webpack安装在项目里面,即和package.json统计目录

    在cmd里面输入:npm  install   webpack  --save-dev


    这里会等待一段时间如下图所示


    安装完之后在根目录下会多出node_modules文件夹,然后就可以写自己的东西了。



    3、在webpack文件下建立文件夹app、public,在文件夹app下新建两个文件test.js和index.js(入口文件),在public文件夹下新建index.html文件,这样就完成项目的基本雏形



    4、在index.html里面输入下面内容

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>test webpack</title>
    </head>
    <body>
    	<div id="root"></div>
    	<script type="text/javascript" src='bundle.js'></script>
    </body>
    </html>


    5、在test.js里面写上内容如下

    // test.js
    module.exports = function(){
    	var test = document.createElement('div');
    	test.textContent = 'here,we are test webpack!';
    	return test;
    };


    6、在index.js里面将test.js的方法引进来

    // index.js
    // 将创建的div元素加进去index.html里面的id=root的元素里面,作为子元素
    var test = require('./test.js');
    document.getElementById('root').appendChild( test() );


    7、下面就可以使用webpack工具进行打包了。在项目根目录下(webpack文件夹下)执行命令:

          node_modules/.bin/webpack  app/index.js   public/bundle.js

          解释:app/index.js 表示项目的入口文件,也就是package.json中的“main”属性对应的值

                    public/bundle.js表示打包后的文件命名为bundle.js,存放在public文件夹下

    但是打包的时候出现下面的问题:

    此问题咱未解决..............



    展开全文
  • 使用Webpack打包单页应用的正确姿势

    千次阅读 2017-02-03 10:46:50
    然而打包的方式多种多样,如何才能最优雅的分离业务代码和依赖库?如何才能最高效的利用缓存?本文将会和大家分享饿了么前端团队总结的各方案优劣、踩过的坑,以及最终的解决方案。对于前端而言,缩短网页加载时间的...

    导语:在现代前端工程中,模块化已经成了前端项目组织文件的标配,网站上线前都会把需要的相关模块预先打包、处理一番。然而打包的方式多种多样,如何才能最优雅的分离业务代码和依赖库?如何才能最高效的利用缓存?本文将会和大家分享饿了么前端团队总结的各方案优劣、踩过的坑,以及最终的解决方案。

    对于前端而言,缩短网页加载时间的常见方式有:

    • 合并文件以减少网络请求数量。
    • 对静态文件设置长达一年的缓存,让浏览器直接从缓存里读取文件。

    为了让更改过的文件能够生效,我们还会给每个文件的文件名里加上一段根据文件内容计算出的hash。每当文件内容改变时,这段hash也会随之改变,所以浏览器会通过网络下载更新过的文件,但没有更新过的文件仍然会从缓存里读取,从而缩短加载时间。

    同理,在开发一个单页面应用的时候,我们通常会将应用的JavaScript代码打包成两个文件:一个用于存放内容很少更改的第三方依赖库,这部分代码的体积一般会比较大;另一个存放更改比较频繁的业务逻辑代码,但它的体积一般比第三方依赖库小。为了方便描述,我们可以分别称这两个文件为vendor.js与app.js。

    有了优化方案,接下来就该选择打包工具了。毫无疑问,时下最流行的就是Webpack了。Webpack在文档里提供了一段简单易懂的配置,用于将项目中的JavaScript代码打包成vendor.js与app.js这两个文件,并分别在它们的文件名里加上一段根据文件内容生成的hash,就像前面说的那样:

    const webpack = require('webpack')
    module.exports = {
      entry: {
        vendor: ['jquery', 'other-lib'],
        app: './entry'
      },
      output: {
        filename: '[name].[chunkhash].js'
      },
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor'
        })
      ]
    }

    但是,几乎所有使用类似配置的人都遇到了一个问题:每当更改了业务逻辑代码时,都会导致vendor.js的hash发生变化。这意味着用户仍然要重新下载vendor.js,即使这部分代码并没有变过。

    为此,开源社区里有人给Webpack指出了这个问题,并吸引了很多人一同讨论,一时之间涌出了很多解决的办法,但这些办法既有人说有用,也有人说没用,而官方却迟迟没有给出一个定论。

    为了得到一个准确的答案,我们尝试了社区里几乎所有的方案。接下来,本文会依次给大家介绍我们尝试过的种种办法,并在文章的最后给出行之有效的解决方案。

    一、使用webpack-md5-hash插件

    const webpack = require('webpack')
    const WebpackMd5Hash = require('webpack-md5-hash')
    module.exports = {
      entry: {
        vendor: ['jquery', 'other-lib'],
        app: './entry'
      },
      output: {
        filename: '[name].[chunkhash].js'
      },
      plugins: [
        new WebpackMd5Hash(),
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor'
        })
      ]
    }

    它的原理是:根据模块打包前的代码内容生成hash,而不是像Webpack那样根据打包后的内容生成hash。经简单测试,在修改业务代码后,它确实能保证vendor.js的hash不被改变,于是我们满心欢喜的将它用到了正式环境,但网站却在上线之后变成了一片空白。

    随后,我们对比了两次编译生成的vendor.js,发现代码里的模块id已经变了,但由于 hash没有更新,所以项目上线后,浏览器直接从缓存里读取了上次上线时的旧版 vendor.js文件,但此时新版的app.js里引用的id为41的模块,在旧版里其实是40,从而引用了错误的模块导致发生了错误,中断了代码的运行。

    不久之后,社区里也有人提出了这个问题

    二、从vendor.js中抽离出Webpack的运行时代码

    有人指出,Webpack的CommonsChunkPlugin会在第一个entry里注入一些运行时代码。按照模块的依赖关系,第一个entry当然就是vendor.js了。这段运行时代码里包含了最终编译出来的app.js的文件名,而app.js的文件名里包含的hash在每次更改业务代码后都会变,所以包含了这段代码的vendor.js的内容也会改变,这才导致它的hash总是不固定。所以,我们需要从vendor.js里抽离出这段运行时代码,才能避免 vendor.js的hash受到影响。

    除此之外,我们还需要用到OccurenceOrderPlugin,将模块按照一定的顺序排序,这才能保证每次编译时模块的id都是相同的,否则模块id一旦改变,就会引起文件内容的变化并影响到hash。

    最终的Webpack配置就像下面这样:

    const webpack = require('webpack')
    module.exports = {
      entry: {
        vendor: ['jquery', 'other-lib'],
        app: './entry'
      },
      output: {
        filename: '[name].[chunkhash].js'
      },
      plugins: [
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor'
        }),
        // 抽离出 Webpack 的运行时代码
        new webpack.optimize.CommonsChunkPlugin({
          name: 'manifest',
          chunks: ['vendor']
        })
      ]
    }

    这个方法确实有效,但我们发现,在删除或新增业务代码中的模块时,vendor.js的hash偶尔还是会受到影响。Webpack的作者也提到了这一点,原文大意如下:

    默认情况下,模块的id是这个模块在模块数组中的索引。OccurenceOrderPlugin 会将引用次数多的模块放在前面,在每次编译时模块的顺序都是一致的……如果你修改代码时新增或删除了一些模块,这将会影响到所有模块的id

    所以,这个方案也不能完全保证vendor.js的hash不受到业务代码的影响。

    三、使用NamedModulesPlugin

    在尝试过第二个解决方案后,我们意识到问题的根源在于Webpack使用模块的引用顺序作为模块的id,这样就不能避免新增或删除模块对其他模块的id产生影响。

    不过,Webpack提供了NamedModulesPlugin插件,它使用模块的相对路径作为模块的 id,所以只要我们不重命名一个模块文件,那么它的id就不会变,更不会影响到其它模块了:

    const webpack = require('webpack')
    module.exports = {
      entry: {
        vendor: ['jquery', 'other-lib'],
        app: './entry'
      },
      output: {
        filename: '[name].[chunkhash].js'
      },
      plugins: [
        new webpack.NamedModulesPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor'
        })
      ]
    }

    但是,相对路径比数字id要长了很多。

    社区对比了使用这个插件后文件的大小,结论是在gzip压缩后,文件并没有大多少。然而我们在项目里实际使用之后,虽然 vendor.js 只比以前大了 1KB,但 app.js 却大了近 15%。

    所以,我们对于这个解决方案仍然不是很满意。

    展开全文
  • webpack 热加载原理探索

    千次阅读 2018-11-02 21:55:57
    每次修改代码后页面直接更新,不需要手动 F5 ,感觉非常惊艳,这体验一旦用上后再也回不去了。 当时的 hot reload 实际上配置的是 live reload,也就是每次修改页面刷新。开发小组件每次更新也蛮快的,但如果一个...
  • webpack打包原理

    千次阅读 2018-03-18 09:39:31
    chunk 多个文件组成的一个代码块,例如把一个可执行模块和它所有依赖的模块组合和一个 chunk 这体现了webpack的打包机制。loader 文件转换器,例如把es6转换为es5,scss转换为css。plugin 插件,用于扩展...
  • 前后端项目对接流程梳理

    万次阅读 2018-04-11 17:54:02
    课程目标 掌握一个电商网站从设计到上线的整个过程所涉及的流程 具备独立开发一个前端项目的能力 网址 ... 架构设计 ...Webpack NodeJs NPM Shell 效率工具 Sublime Chrome Charles Gi...
  • VUE+TS+WEBPACK框架的项目实践

    万次阅读 2018-01-31 11:58:20
    一、作者简介 WONDER专注于框架的研究,致力于提升效能,解放生产力。包括但不限于设计流程化,重构流程化,前端流程化,基于数据流、状态流的自动化测试。致力于基于javascript语言的全平台解决方案的研究(包括...
  • 通过webpack从零开始搭建React项目

    千次阅读 2019-04-26 14:12:21
    从零开始搭建React项目 1. Webpack基础概念 ...代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功...
  • Vue开发看这里就够了

    万次阅读 2018-03-08 11:09:10
    Vue -渐进式JavaScript框架介绍vue 中文网vue githubVue.js 是一套构建用户界面(UI)的渐进式JavaScript框架库和框架的区别我们所说的前端框架与库的区别?Library库,本质上是一些函数的集合。每次调用函数,实现一...
  • 减少webpack打包时间 1.优化Loader 对于Loader来说,影响打包效率首当齐冲必属Babel了。因为babel会将代码转为字符串生成AST,然后对AST继续进行转变最后生成新的代码,项目越大,转化代码越多,效率就越低。当然了...
  • 带你用合理的姿势使用webpack4(下)

    千次阅读 2018-10-12 10:30:35
    推荐先阅读 webpack 入门教程之后再来阅读本文。 Webpack 4 和单页应用入门 手摸手,带你用合理的姿势使用 webpack4 (上) 本文为手摸手使用 webpack4(下),主要分为两部分: 怎么合理的运用浏览器缓存 怎么...
  • 看懂前端脚手架你需要这篇WEBPACK

    千次阅读 2017-11-06 15:10:55
    Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过loader ...
  • webpack性能优化

    千次阅读 2017-08-01 01:39:41
    webpack无疑是强大的,强大到没有朋友,webpack的设计初衷也是伟大的,它可以编译打包我们的代码,借助loader,使得我们可以使用各种es6/es7的特性,可以使用sass/less,可以编写react代码等等。
  • vue按需加载实现

    千次阅读 2018-05-04 11:23:37
    webpack打包会自动将所有依赖的JS代码打入一个文件,如果工程特别大,依赖的内容特别多的话,就会导致该文件特别的大,而大文件加载会导致性能不是特别的好。此时按需加载就显得尤为重要。参考:点击打开链接未按需...
  • 利用webpack搭建脚手架一套完整流程

    千次阅读 2019-06-28 09:32:52
    我们的目标是利用webpack搭建一个基于react + react-router +dva + es6 + less + antd用于中后台开发的脚手架,同学们可能会说社区里那么多优秀的脚手架为什么还要自己搭,而且网络上这类文章也非常的多,没有再重复...
  • 如何打造一个自定义的bootstrap? 前言 一般我们用bootstrap呐,都是用的从官网或github下载下来build好了的版本,千人一脸呐多没意思。当然,官网也给我们提供了自定义的工具,如下图所示,但每次要改些什么就要...
  • Vue 项目性能优化方案

    千次阅读 2019-08-23 10:01:29
    但 Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。本文是作者通过实际项目的优化实践进行总结而来,希.....
  • Vue 知识点汇总(下)--附案例代码及项目地址

    千次阅读 多人点赞 2020-01-14 01:53:43
    文章目录Vue预备知识与后续知识及项目案例一、简介1.Vue (读音 /vjuː/,类似于 view)的简单认识2.Vue.js安装二、Vue知识量化三、内容1、Webpack 详解什么是Webpack?前端模块化**和grunt/gulp的对比**webpack安装...
  • Webpack性能优化

    千次阅读 2019-08-27 11:09:54
    Webpack是现在主流的功能强大的模块化打包工具,在使用Webpack时,如果不注意性能优化,有非常大的可能会产生性能问题,性能问题主要分为开发时打包构建速度慢、开发调试时的重复性工作、以及输出文件质量不高等,...
1 2 3 4 5 ... 20
收藏数 684
精华内容 273
关键字:

webpack 原理 抽离公共代码