npx webpack
    webpack -> config -> 打包入口 输出目录 -> 入口文件
    -> 分析是否有依赖,以及模块的路径 -> 解析处理的内容(es6 + es5)
    -> chunkcode 缺失函数,require exports

    1. (function() {
    2. // 缺失函数补齐
    3. require
    4. eval(chunkcode)
    5. exports
    6. )({
    7. // 依赖模块, 入口模块的路径为key
    8. // key: 模块的处理后的chunkcode
    9. })
    10. // simple-webpack
    11. // webpack.config.js
    12. // entry
    13. // output
    14. // mode
    15. // Lib
    16. // webpack.js
    17. // Webpack class
    18. // run
    19. // 入口文件的路径
    20. // 分析文件的内容
    21. // 模块依赖路径,内容处理,chunkcode
    22. // 递归处理所有依赖, index.js > a.js > b.js
    23. // 生成bundle结构,生成文件,放入dist目录
    24. // bundle.js
    25. // 引入 lib/webpack.js
    26. // 引入 webpack options
    27. // complier = Webpack(config)
    28. // Compiler.run()
    1. const fs = require('fs')
    2. const path = require('path')
    3. const parser = require('@babel/parser')
    4. const traverse = require('@babel/traverse').default
    5. const { transformFromAst } = require('@babel/core')
    6. module.exports = class Webpack {
    7. constructor(options) {
    8. this.entry = options.entry
    9. this.output = options.output
    10. this.modules = []
    11. }
    12. run() {
    13. let info = this.parse(this.entry)
    14. this.modules.push(info);
    15. for (let i = 0; i < this.modules.length; i++) {
    16. let item = this.modules[i]
    17. let { dependencies } = item;
    18. if (dependencies) {
    19. for (let key in dependencies) {
    20. this.modules.push(this.parse(dependencies[key]))
    21. }
    22. }
    23. }
    24. let obj = {}
    25. this.modules.forEach(item => {
    26. obj[item.entryFile] = {
    27. code: item.code,
    28. dependencies: item.dependencies
    29. }
    30. })
    31. this.file(obj)
    32. }
    33. file(code) {
    34. let newCode = JSON.stringify(code);
    35. let bundle = `(function(modules){
    36. function require(module) {
    37. function newRequire(relativePath) {
    38. return require(modules[module].dependencies[relativePath])
    39. }
    40. var exports = {};
    41. (function(require,exports,code){
    42. eval(code)
    43. })(newRequire, exports, modules[module].code)
    44. return exports;
    45. }
    46. require('${this.entry}')
    47. })(${newCode})`
    48. let distPath = path.join(this.output.path, this.output.filename);
    49. fs.writeFileSync(distPath, bundle, 'utf-8');
    50. }
    51. parse(entryFile) {
    52. let content = fs.readFileSync(entryFile, 'utf-8')
    53. let ast = parser.parse(content, {
    54. sourceType: 'module'
    55. })
    56. let dependencies = {}
    57. traverse(ast, {
    58. ImportDeclaration({ node }) {
    59. dependencies[node.source.value] = './' + path.join(path.dirname(entryFile), node.source.value)
    60. }
    61. })
    62. let { code } = transformFromAst(ast, null, {
    63. presets: ['@babel/preset-env']
    64. })
    65. return {
    66. entryFile,
    67. code,
    68. dependencies,
    69. }
    70. }
    71. }