模块导入导出

  • bundle 是入口 js,也就是你的 html 会直接引用的 js 文件。
  • chunk 是webpack依据依赖打包的懒加载js文件,我们不会直接引用,一般都是 webpack 自动加载。

导出

ES6

  • export
// 具名导出
export var Count = 5;
export function Multiply(a, b) {
  return a * b;
}

// 默认导出
export default {
  // Some data...
};

// 直接从另一个文件导出
export * from './src/echarts';
export { default as IhrMore } from '@/components/common/more/more.vue'

CommonJS

  • module.exports调用者通过 require 对模块进行调用时返回的值(默认为一个新对象)。
module.exports = function (source, map) {
    this.callback(
        null,
        `export default function (Component) {
            Component.options.__docs = ${
                JSON.stringify(source)
            }
        }`,
        map
    )
}

AMD

  • define(不能在异步函数中调用?)
define([name: String], [dependencies: String[]], factoryMethod: function(...))
define(value: !Function)

webpack 内置的 LabeledModulesPlugin 插件特殊导出导入方式

  • export 标记可以出现在函数声明或变量声明之前。函数名或变量名是导出值的标识符。以异步的方式使用,可能不会达到预期的效果。
export: var answer = 42;
export: function method(value) {
  // 做一些操作……
};
  • 使当前作用域下,可访问所依赖模块的所有导出。require 标签可以放置在一个字符串之前。依赖模块必须使用 export 标签导出值。CommonJS 或 AMD 模块无法通过这种方式,使用标签模块的导出。
// some-dependency.js使用export导出
export: var answer = 42;
export: function method(value) {
  // 执行一些操作……
};

// 其他模块使用require:导入
require: 'some-dependency';
console.log(answer);
method(...);

同步导入

ES6

  • import
import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';

CommonJS

  • 以同步的方式检索其他模块的导出。var myModule = require('my-module');
  • 以同步的方式获取模块的 ID。require.resolve('dependency')由编译器(compiler)来确保依赖项在最终输出 bundle 中可用。(虽然返回的是模块ID但实际上指向的模块已经被加载到当前模块内了)
    • webpack 中模块 ID 是一个数字(而在 NodeJS 中是一个字符串 -- 也就是文件名)。
  • 多处引用同一个模块,最终只会产生一次模块执行和一次导出,所以提供了这个接口以获取模块缓存。require.cache[require.resolve('dependency')];
  • 删除模块。delete require.cache[require.resolve('dependency')];

Webpack

  • require.context程序化的定义导入,能够实现批量导入。返回一个require 函数,该函数有三个属性:resolve 、keys、id(这个require 函数并不是CommonJS中的require函数)
    • resolve: 是一个函数,他返回的是被解析模块的id
    • keys: 是一个函数,他返回的是一个数组,该数组是由所有可能被上下文模块解析的请求对象组成(由文件名字符串组成的数组)
    • id:上下文模块的id(?)
    • 该require 函数传入keys返回的数组中的文件名时,返回组件的配置信息
// 语法
require.context(
  directory: String,    // 其组件目录的相对路径
  includeSubdirs: Boolean    // 是否查询其子目录 /* 可选的,默认值是 true */,
  filter: RegExp    // 匹配基础组件文件名的正则表达式 /* 可选的 */
)

// 例如
import BaseButton from './components/BaseButton.vue'
import BaseIcon from './components/BaseIcon.vue'
import BaseInput from './components/BaseInput.vue'
// 可写为
const requireComponent = require.context(
  './components',    // 其组件目录的相对路径
  false,    // 是否查询其子目录
  /Base[A-Z]\w+\.(vue|js)$/    // 匹配基础组件文件名的正则表达式
)

// require.context返回一个函数requireComponent(fileName)
// 猜测该函数可以传入一个参数,该参数为正则匹配值去掉后缀后的字符串,返回导入的模块
// require.contex和resolve不同的是区分export default和export(resolve是指哪个?)
requireComponent.keys().forEach(fileName => { // keys是一个函数,他返回的是一个数组,该数组是由所有可能被上下文模块解析的请求对象组成(由文件名字符串组成的数组)
  const componentConfig = requireComponent(fileName)    // 获取组件配置
  // 获取组件的 PascalCase 命名
  const componentName = upperFirst( // lodash中的方法,转化字符串的首字母为大写
    camelCase( // lodash中的方法,把字符串转为首字母为小写的驼峰式
      // 剥去文件名开头的 `./` 和结尾的扩展名
      fileName.replace(/^\.\/(.*)\.\w+$/, '$1')    //匹配 ./ 和 .[a-zA-Z_] 结尾之间的所有值,'$1'是replace的用法:使用字符串作为参数,'$1'代表第 1 个括号匹配的字符串替换匹配到的值
    )
  )

  // 全局注册组件
  Vue.component(
    componentName,
    // 如果这个组件选项是通过 `export default` 导出的,
    // 那么就会优先使用 `.default`,
    // 否则回退到使用模块的根。
    componentConfig.default || componentConfig
  )
})


// require.context返回一个函数,拥有方法resolve用以返回引入的模块的id,猜测参数为正则匹配值去掉后缀
var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA');
  • require.resolveWeak不会将 module 引入到 bundle 中。这就是所谓的"弱(weak)"依赖。(作为辅助打包的条件,还可用于服务端渲染SSR?)
if(__webpack_modules__[require.resolveWeak('module')]) {
  // 模块可用时,执行一些操作……
}
if(require.cache[require.resolveWeak('module')]) {
  // 在模块被加载之前,执行一些操作……
}

// 你可以像执行其他 require/import 方法一样,
// 执行动态解析(“上下文”)。
const page = 'Foo';
__webpack_modules__[require.resolveWeak(`./page/${page}`)];

异步导入

ES6

  • import 规范不允许控制模块的名称或其他属性,因为 "chunks" 只是 webpack 中的一个概念。幸运的是,webpack 中可以通过注释接收一些特殊的参数,而无须破坏规定:
  • webpackInclude:在导入解析(import resolution)过程中,用于匹配的正则表达式。只有匹配到的模块才会被打包(仅文件名)。
  • webpackExclude:在导入解析(import resolution)过程中,用于匹配的正则表达式。所有匹配到的模块都不会被打包(仅文件名)。
  • webpackChunkName:新 chunk 的名称。从 webpack 2.6.0 开始,[index] and [request] 占位符,分别支持赋予一个递增的数字和实际解析的文件名。
  • webpackMode:从 webpack 2.6.0 开始,可以指定以不同的模式解析动态导入。
    • "lazy"(默认):为每个 import() 导入的模块,生成一个可延迟加载(lazy-loadable) chunk。
    • "lazy-once":生成一个可以满足所有 import() 调用的单个可延迟加载(lazy-loadable) chunk。(这种模式仅在部分动态语句中有意义,例如 import(./locales/${language}.json),其中可能含有多个被请求的模块路径。)
    • "eager":不会生成额外的 chunk,所有模块都被当前 chunk 引入,并且没有额外的网络请求。仍然会返回 Promise,但是是 resolved 状态。和静态导入相对比,在调用 import()完成之前,该模块不会被执行。
    • "weak":尝试加载模块,返回 Promise,但是只有在客户端上已经有该 chunk 时才成功解析。如果该模块不可用,Promise 将会是 rejected 状态,并且网络请求永远不会执行。
  • ./locale/${language}至少需要一些文件的路径信息,webpack打包时会把所有./locale/都打包到一个chunk下
// 单个目标
import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  'module'
);

// 多个可能目标
import(
  /* webpackInclude: /\.json$/ */
  /* webpackExclude: /\.noimport\.json$/ */
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  `./locale/${language}`
);

CommonJS

  • require.ensure
require.ensure(
  dependencies: String[], // 字符串构成的数组,声明 callback 回调函数中所需的所有模块。
  // 只要加载好全部依赖,webpack 就会执行此函数。
  // require 函数的实现,作为参数传入此函数。当程序运行需要依赖时,可以使用 require() 来加载依赖。函数体可以使用此参数,来进一步执行 require() 模块。这里的参数require必须为该名称才能保证被webpack解析
  callback: function(require), 
  errorCallback: function(error), 
  chunkName: String // 建出的 chunk 的名字。通过将同一个 chunkName 传递给不同的 require.ensure() 调用,我们可以将它们的代码合并到一个单独的 chunk 中,从而只产生一个浏览器必须加载的 bundle。
)

AMD

  • requirerequire(dependencies: String[], [callback: function(...)])

Webpack

  • require.include引入一个不需要执行的依赖,这可以用于优化输出 chunk 中的依赖模块的位置。
equire.include('a');
require.ensure(['a', 'b'], function(require) { /* ... */ });
require.ensure(['a', 'c'], function(require) { /* ... */ });

// 这会产生以下输出:
// entry chunk: file.js and a
// anonymous chunk: b
// anonymous chunk: c
// 如果不使用 require.include('a'),输出的两个匿名 chunk 都有模块 a。

CSS 模块化导入使用方法

  • import cssName frome 'cssUrl'
    • 在 JavaScript 中作为 CSS Modules 导入 CSS 或其它预处理文件,该文件应该以 .module.(css|less|sass|scss|styl) 结尾
    • 不能配合使用Scope CSS ?
    • 只是一个模块化处理入口,返回一个空对象
    • 不使用 CSS Modules 应该也可以直接使用预处理器语言
  • @import url("fineprint.css");具体使用方法,似乎是在style中引入css的方法
    • @import "@/variables.scss"; 在vue.config.js中存在,?
  • link 标签引入在项目中会被作为模块处理?
原文地址:https://www.cnblogs.com/qq3279338858/p/9875995.html