You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles.
Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a require()/import statement, use the raw-loader to transform it before you add it to the bundle.
webpack supports all browsers that are ES5-compliant (IE8 and below are not supported). webpack needs Promise for import() and require.ensure(). If you want to support older browsers, you will need to load a polyfill before using these expressions.
/******/(function(modules){// webpackBootstrap/******/// The module cache/******/varinstalledModules={};/******//******/// The require function/******/function__webpack_require__(moduleId){/******//******/// Check if module is in cache/******/if(installedModules[moduleId]){/******/returninstalledModules[moduleId].exports;/******/}/******/// Create a new module (and put it into the cache)/******/varmodule=installedModules[moduleId]={/******/i: moduleId,/******/l: false,/******/exports: {}/******/};/******//******/// Execute the module function/******/modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);/******//******/// Flag the module as loaded/******/module.l=true;/******//******/// Return the exports of the module/******/returnmodule.exports;/******/}/******//******//******/// expose the modules object (__webpack_modules__)/******/__webpack_require__.m=modules;/******//******/// expose the module cache/******/__webpack_require__.c=installedModules;/******//******/// define getter function for harmony exports/******/__webpack_require__.d=function(exports,name,getter){/******/if(!__webpack_require__.o(exports,name)){/******/Object.defineProperty(exports,name,{enumerable: true,get: getter});/******/}/******/};/******//******/// define __esModule on exports/******/__webpack_require__.r=function(exports){/******/if(typeofSymbol!=='undefined'&&Symbol.toStringTag){/******/Object.defineProperty(exports,Symbol.toStringTag,{value: 'Module'});/******/}/******/Object.defineProperty(exports,'__esModule',{value: true});/******/};/******//******/// create a fake namespace object/******/// mode & 1: value is a module id, require it/******/// mode & 2: merge all properties of value into the ns/******/// mode & 4: return value when already ns object/******/// mode & 8|1: behave like require/******/__webpack_require__.t=function(value,mode){/******/if(mode&1)value=__webpack_require__(value);/******/if(mode&8)returnvalue;/******/if((mode&4)&&typeofvalue==='object'&&value&&value.__esModule)returnvalue;/******/varns=Object.create(null);/******/__webpack_require__.r(ns);/******/Object.defineProperty(ns,'default',{enumerable: true,value: value});/******/if(mode&2&&typeofvalue!='string')for(varkeyinvalue)__webpack_require__.d(ns,key,function(key){returnvalue[key];}.bind(null,key));/******/returnns;/******/};/******//******/// getDefaultExport function for compatibility with non-harmony modules/******/__webpack_require__.n=function(module){/******/vargetter=module&&module.__esModule ?
/******/functiongetDefault(){returnmodule['default'];} :
/******/functiongetModuleExports(){returnmodule;};/******/__webpack_require__.d(getter,'a',getter);/******/returngetter;/******/};/******//******/// Object.prototype.hasOwnProperty.call/******/__webpack_require__.o=function(object,property){returnObject.prototype.hasOwnProperty.call(object,property);};/******//******/// __webpack_public_path__/******/__webpack_require__.p="";/******//******//******/// Load entry module and return exports/******/return__webpack_require__(__webpack_require__.s="./src/index.js");/******/})/************************************************************************//******/({/***/"./src/index.js":
/*!**********************!*\ !*** ./src/index.js ***! \**********************//*! no static exports found *//***/(function(module,exports){eval("console.log(\"hello world\");\n\n//# sourceURL=webpack:///./src/index.js?");/***/})/******/});
importfsfrom'fs'importpathfrom'path'exportdefaultfunction(arr=[]){varpackageJson,externals={};try{varpackageJsonString=fs.readFileSync(path.join(process.cwd(),'./package.json'),'utf8');packageJson=JSON.parse(packageJsonString);}catch(e){throw'can not find package.json'}varsections=['dependencies'].concat(arr);sections=newSet(sections)vardeps={};sections.forEach(function(section){Object.keys(packageJson[section]||{}).forEach(function(dep){externals[dep]='commonjs '+dep;});});returnexternals}
什么是webpack?
简单来说就是一个打包工具, 某种程度就是传统语言中的linker,所以只要你写javascript就不可能离开webpack。
当前webpack版本: 4.42.0
从最小化开始
yarn init -y
起步, 然后开一个src/index.jsindex.js
直接运行webpack, 默认entry为'./src',即./src/index.js, 默认output是./dist/main.js,然后就能生产一行超长的js。
默认情况下等同于如下:
webpack.config.js
文档中指出,首先需要了解几个核心概念:
Entry & Output
Entry就是webpack构建dependency Graph的起点,即程序入口。Output就是打包后的产物。
支持多entry,这个后面再说。
Loaders
从entry开始,webpack会追踪所有依赖,但默认的webpack只跟进javascript和json的依赖,将其打包,webpack并不认识css, svg,所以需要loader来指引webpack如何转换(transform)
这里表示当依赖碰到'.txt'结尾的文件交由raw-loader进入webpack
Plugins
如果说loader是根据文件名来做分类处理,Plugins就如同koa/express中的middleware, 对整体输出做transform。
webpack.config.js
Mode
可以将Mode理解为webpack采用的configuration,默认是production
index.js
直接运行NODE_ENV为undefined,通过webpack后运行输出'production',观察./dist/main.js,你会发现在bundle的过程中webpack直接将process.env.NODE_ENV替换为'production', 不再依赖于外部的环境变量。
此时输出的依然是production。
除了对环境变量的影响,更多是采用的优化策略不同,具体见这里。
看下面这句代码:
首先肯定是不推荐去写process.env.NODE_ENV,但这句在非webpack下是没问题的,但是如果webpack后运行会报错,
换句话说,写代码的时候需要考虑一下webpack的感受,否则怎么死的都不知道。
此外,__dirname会被替换为/, 而__filename的路径也变成/,所以这些都是打包后带来的副作用。
Browser Compatibility
Node部分则是需要8.x以上即可。
在基本了解了这几个概念以后,我们尝试将mode改为development,你会得到的main.js如下
正好100行,强烈建议在debug一下这个100行,你大概就能理解一个基本的webpack输出的routine了,这个文件是不依赖任何外部文件就可以运行,webpack将node的require翻译成了自己的方式进行管理。
Q: 为什么将conole.log封装到eval中呢?
A: 添加sourcemap,通过devtool可以在运行bundle代码是定位到source file, 具体可以查看JavaScript Source Map 详解 - 阮一峰的网络日志
我们来增加一个内部依赖,
app.js
index.js
webpack后的./dist/main.js
很容易理解吧,再来看外部依赖,
index.js
main.js
先不说原理,看结果来说,就是webpack碰到外部lodash时,这时会先导入自身的globals和modules两个模块,然后导入lodash, 最后导入index.js
这样的好处是生成的js解决了所有依赖问题,直接复制到服务器上就可以运行,坏处也很明显,就是当文件多了以后这个文件要爆炸,单单是加了lodash就从3.8K变为552K, production为62K,看情况取舍。
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies), 这时候就需要用到externals配置。
此时生成main.js
你会发现其实外部依赖就是直接利用node的require进行动态加载。
我试了一下,也是OK的,其实就是一个意思,当碰到lodash时如何处理,
当你希望排除所有依赖包的时候,你不可能一个个来写,所以可以直接利用externals-dependencies, 源代码只有21行,
实质就是遍历所有node_modules然后返回一个array, pkg => 'commonjs pkg'。
官网上也说externals更多是服务library developers, 避免重复加载相同的依赖,我感觉如果是node落地服务,更多的倾向全量打包,一个js搞定,很多时候服务器是没有网络无法做npm install,这个时候就特别有价值。
到这里我们就可以玩一个花出来,比如说在bundle后如何混合加载unbundle的javascript file,
index.js
./dist/plugins/index.js
再来,在Module Resolution中指出webpack会通过分析require/import指令来构建dependency graph,但是支持的require也是有要求的:
比如说 index.js
node直接运行没问题,但是webpack后运行报错
Error: Cannot find module './app'
但是,
这样就ok,原因是require不能单单是变量,一定要有一部分字符串才能引导进require.context方式。
如果想加载多个文件,
如果是目录对应
EOF
参考:
The text was updated successfully, but these errors were encountered: