Press "Enter" to skip to content

前端模块化开发实验(二)—— 纯JS 模块的Welcome world

当我们往/src 目录创建新源文件,或拷入新资源数据(例如图片),它们都均属于某一种类型 「web模块」类型 的意义是说,它是有某种 固定格式,包括外部形式,和内部构成。例如 V模块类型一定会访问DOM的,样式模块一定有样式定义,并提供给V模块使用等等。本文我们正式开始写V模块。

上一篇我们 为前端模块化开发 做了最基础的工作,包括webpack基础配置(包括开发服务器),和index模块的创建,还创建了一测试的V模块app.js。

然而,这些基础配置是不完整的。第一,app.js没有被转译为更通用的 ES5代码;第二,没有配置支持开发CSS和资源模块。本文任务就是配置更完整的 webpack,并且开发更完整功能 Welcome world 作演示。

Welcome world UI结构

Welcome world UI结构
Welcome world UI结构
index
    L app
        L Layout
            L css
            E Greeting
                L css, png

源文件格式

在开始配置 webpack 之前,我们先弄清一些关于 源文件格式的概念。有webpack使用经验的知道,我们既可以用ES6写V模块,也可以用Typescript写,也可用 JSX;同样,我们可以直接写 CSS,也可以用SASS。只要我们作相应的配置,我们可以使用不同的源文件格式写web模块。但是,webpack 目标是打包符合标准的 能在大多数浏览器上运行的代码,所以编写的源文件格式不对时(例如浏览器不能运行TS),要先转译,这就是 loader(https://webpack.js.org/loaders/) 的任务——打包前先进行格式转换。

本文选择 使用 ES6 格式编写 V模块,CSS 写 样式模块(不用SASS),和直接使用图片格式 作 资源模块。注意,这里CSS不用转译 还是需要配置loader,而且还是两个,显然 loader的任务 没有固定标准,因模块类型而有不同。

好,理论到处为止,开始动手。

Babel 和 ES6格式模块

要转译打包 ES6格式源文件,我们需要安装 babel-loader  和 babel 本身,babel要安装包括 核心(@babel/core )和 基本预设(@babel/preset-env ):

$ npm i -D babel-loader @babel/core @babel/preset-env

配置 webpack.config.js

module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    }
  ]
}

css-loader 和 原始CSS格式模块

样式开发有很多技术,例如有 CSS-in-JS,有CSS preprocessor,有PostCSS,每种需要特定的 loader转译,本文暂时都不用。为了支持样式模块开发,至少安装两个webpack loader:

  • css-loader – 解释 CSS imports,生成依赖图
  • style-loader – 将样式定义注入 DOM
$ npm i -D css-loader style-loader

配置 webpack.config.js

注意loader加载顺序,先解释,再注入,倒序加载:

module.exports = {
  /* ... */
  module: {
    rules: [
    {
       test: /\.css$/,        
       use: ['style-loader', 'css-loader'],      
    },    ],
  },
}

layout V模块

好了,现在我们开始编写 V模块 ,测试这些webpack配置。从上面草图中,我们看到了两个V模块的大概内容和关系,先分析 layout V:

  • 第一,它是个典型的“哑UI”,没有交互状态,就是一个布局容器;
  • 第二,它和 greeting V有嵌套调用关系;greeting 是它的子V;
  • 第三,它有一个 内容垂直和水平居中的样式定义,为了演示样式模块,将定义独立成layout.css;
  • 第四,app模块 加载 layout模块;

layout.css

.centerbox {
    /*https://coryrylan.com/blog/how-to-center-in-css-with-flexbox*/
    height:100vh;
    display: flex;
    justify-content: center;
    color: green;
    align-items: center;
}
.greeting{
    display: inline-block;
}

greeting.js

// Create Greeting node
const Greeting = document.createElement('h1');
Greeting.textContent = 'Hello Web World!';

const box = document.createElement('div');
box.classList = "greeting";
box.append(Greeting)

export default box;

layout.js

import './layout.css';
import Greeting from './greeting.js';

const Container = document.createElement('div');
Container.classList = "centerbox";
Container.append(Greeting);

export default Container;

greeting V 模块

布局V 引入一个水平和垂直居中的样式模块,接着开发 Greeting这个V模块。

为了演示 V模块类型的丰富性,Greeting V 有图片,和简单的用户交互(状态交互会在下一文中演示)。为了支持 图片资源模块,要先配置webpack。

webpack 5之后 对 资源模块有内置支持,不需要像4时需要安装额外loader了:

module.exports = {
  /* ... */
  module: {
    rules: [
      		// Images      
        {        
            test: /\.(?:ico|gif|png|jpg|jpeg)$/i,        
            type: 'asset/resource',     
     },    ],
  },
}

然后我们 “制作”(拷贝)一个图片模块在 ./images/webpack.gif

// Create Greeting node
import webpack_logo from './images/webpack.gif'

const Logo = document.createElement('img');
Logo.src = webpack_logo;
const Greeting = document.createElement('h1');
Greeting.textContent = 'Hello Web World!';

const box = document.createElement('div');
box.classList = "greeting";
box.append(Logo);
box.append(Greeting);

export default box;

再增加一个交互输入:

...
//////// 3 User Input /////////
const userInput = document.createElement('input');

//////// 4 Submit Button /////////
const btn = document.createElement('button');
btn.innerText = "click me";
btn.onclick = hello;

/////// 5 submit event handler ////////
function hello(e){
    if(userInput.value.trim() == "") return alert("What's you name?");

    let name = userInput.value;
    Greeting.textContent = `Hello,${name} Welcome Web world!`;
    console.log(e);
    return;
}
....

小结

Greeting 这个V 模块 是本实验的核心,然而作为一个V,它几乎没有什么功能,代码居然已经有40多行。因为每个UI元素都要手动创建,设置,绑定事件等等。这也是早期web前端编程的样子了。后来的一代MVC框架,可以引jquery和 template技术 简单化 V模块开发。不过,本系列不计划介绍像Backbone这样的框架,直接使用 React 和Vue 改造。

源码

这里(https://github.com/nakeman/modular-web-frontend-webpack-js),在tag v0.2上。

 

 

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *