4

前端模块化开发实验(一)——模块概念以及webpack基础配置

 1 year ago
source link: https://nakeman.cn/blog/modular-web-frontend-webpack-js/#start_scrollspy
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前端模块化开发实验(一)——模块概念以及webpack基础配置

现在web 应用前后端分离,前端独立成一个专业,并且还工程化了,这个事实对于 经历过早期Web1.0和2.0的开发者而言,刚接触时应该是比较新奇的。

应用软件网络化,web services 成为不可阻挡的 软件应用的风潮。作为一名技术开发者,一名经历过早期web开发的人,我最感兴趣是 前端工程化的概念——什么东西被工程组件化了。

前端工程模块化的发展

有过早期经验有开发者应该知道,一支web应用 都是由多页组成的,页面在后端“渲染”生成;每个页面的交互功能都由自己js实现,当页面交互功能比较多时,都会让开发者在维护上的头痛。

当页面交互功能需求增长时,业界第一反应不是工程化技术,而是结构化和动态化技术。动态化是AJAX和Jquery的流行,结构化是第一代的MVC框架的出现,例如Backbone, Angular1。

前端MVC框架的出现应该是前端工程化的肇始,但它不成熟,尤其是第一代的。我个人为像webpack这样 module bundle工具出现才是 前端工程化 的真正的到来。为什么这么说,因为webpack 等 module bundle工具引入工程最需要“web模块”的概念。

工程化最主要技术基础,是分立制作的 工程构件,每种构件有自己的 独特的专业和特性。这话什么意思?意思是真正工程化是,我们可以独立制作不同功能的构件,然后根据需求像 拼积木那样 搭建想要的复杂功能。

web前端工程化最大的困难是,它 (web app)可怎么被分割为不同逻辑功能构件。有 webpack 使用经验的人都知道,不但js模块可以import,连css , 图片,字体都可以 import,这就是现在发展的 成果。但是在 webpack出现之前,只有 js 能被模块化,而且存在多种技术(commonjs, requirejs, AMD)。

前端模块化的基础原理

要对 web前端 工程化,第一 要件是清晰掌握 web app的本质形式,和它的可能逻辑构成;第二,是在第一个条件之上找 到一种技术实现,包括1)构件的表达,2)构件复合的机制,例如 webpack 处理 css 样式 就是一种工程化技术例子;而 MVC,MVVM是web app逻辑构成 比较流行的努力。

工程化成熟利好表现是,我们可以使用标准工程构件 分析、分解、设计和开发 我们的需求。在过去,web app 以页面为单位进行分析,设计和开发的,那是一种直观的未成熟的结构化开发。现在,有了webpack ,我们可以使用“web模块”进行工程化建构。

本系列文将以一个简单的例子,演示一下目前 前端工程化的样子——以webpack为例子,演示不同 web模块种类,及它们的复合原理,并且定制一个相对应的webpack配置。

我们选择一支简单但比较全面的web app 前端实现,演示可能的逻辑构件,和构件复合原理。

web 模块

在开始 1)分析需求和2)配置webpack之前,我们必须理解 何为 「标准工程构件模块」,以及有什么样的种类。

作为一种运行在web浏览器上的应用程序,主要有以下几种构件模块:

  • 第一,与用户交互和与DOM有关联的 构件模块,可定名为 V 模块
  • 第二,样式模块,因为样式有自己的复杂性,可独立专业制作;
  • 第三,包括 图片,字体等的 资源模块;资源可理解为 JS程序 特别的外部程序数据,通过url连接;
  • 第四,还有一种 和以上三种都不同的 通用模块
  • 第五,React ,Vue 的模块,此模块 本文暂不处理;
  • 第六,还有一个特别的模块,就是 index模块

对这些模块类型需要补充几点:

  • 第一,除了index模块,所有模块都是由 webpack loader处理,并“打包”入 bundle的;
  • 第二,index模块 负责加载 bundle(通过scripte标签),包括外链的css ;
  • 第三,这里的“模块”是 web 逻辑的,与 JS的语言程序模块不同,JS模块可理解为物理模块;
  • 第四,样式和资源模块没有独立意义,它们都是为构建V 模块准备的;

一支 web app逻辑构成 标准是,它至少有一个index模块,一个或以上的V模块;V模块可选的由一个或以上的 样式和资源模块组成。

Welcome world应用

为了保证例子的基础 且全面 演示 一支 web 前端应用,我选择了一个 特别的Welcome world应用(相对于传统hello world)。功能非常简单,主页面有一个输入框,提示输入名字,点击后 显示欢迎语:XXX ,欢迎来到前端世界(Welcome to Web world)。

结构上,它由一个index 模块,两个 V模块(一个layout和一个主体内容),V模块会有一些样式,和图片。

为了支持这些 三种模块类 型的开发,我们必须配置webpack的 index插件,babel , css , asset loader。开始动手吧。

webpack 和 index模块

webpack 的工作 就是将 所有具有依赖关系的“web模块”打包成一个 bundle.js文件,然而 .js 自己并不会运行,在浏览器上要依赖一个页面执行它,这就是index.html。

index.html可直接在发布目录上手动创建,但是,更多理由表明,和bundle.js并行的 index 也应该要由 “源文件” 动态编译 ,和打包发布。「源文件」这个概念要特别解释一下,位于 src目录 的所有数据 都是 web模块 的「 源文件」,它不能直在浏览器上运行,必须进行“编译”和打包。

webpack 安装配置


$ mkdir modular-web-frontend-webpack-js && cd modular-web-frontend-webpack-js
$ npm init -y
$ npm i -D webpack webpack-cli
webpack.config.js

const path = require('path')

module.exports = {
  entry: {
    main: path.resolve(\_\_dirname, './src/index.js'),
  },
  output: {
    path: path.resolve(\_\_dirname, './dist'),
    filename: '\[name\].bundle.js',
  },
}

package.json

"scripts": {
    "build": "webpack --mode development"
}

index插件及和index模块

由于 index.html 在 bundle.js之外,故不由loader处理,由plugin处理(html-webpack-plugin)。

安装index 插件并配置webpack,创建src源文件目录,并在 src目录内创建 index 模块的”源文件“ —— index.template.html。

$ npm i -D html-webpack-plugin

webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  /* ... */

  plugins: [    
  new HtmlWebpackPlugin({      
    title: 'Hello Web world!!',      
    template: path.resolve(__dirname, './src/index.template.html'), 
    filename: 'index.html', 
   }),  
],}

src/index.template.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>

  <body>
    <div id="root"></div>
  </body>
</html>

bundle入口 index.js

index 模块 负责加载 bundle.js,所以 bundle.js可以 看成是 index模块 的子模块。而我们常常也将 bundle的入口模块也定名为index,这会引起困惑,不过也证明了它们之间有逻辑上的关系。这关系就是:

  1. index.html是由index插件生成的,boundle.js(index.js入口)由于loader生成的;
  2. index.template.html才对应index.js,同属于源文件模块;
  3. 与其他V有独立的DOM节点不同,index.js只负责访问index.html的根节点,并且只它(作为bundle一部分)访问

index.js主要任务,加载程序入口模块(下面的app.js),和挂接到index.html的根节点上:

import Greeting from './app.js'

// Append Greeting node to the DOM
const approot = document.querySelector('#root')
approot.append(Greeting)

程序入口 app.js和第一个V模块

这个模块是 整个程序的起点。此模块现在是访问DOM的,是一个简单的V模块,因为只是演示。实际项目中,这个模块会比较复杂,一般都不是V模块,而是为 更复杂V模块准备条件的特殊模块。

src/app.js

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

export default Greeting;

webpack dev server

到此我们可以进行 编译、打包和测试了,打包好的数据会在发布目录dist上。为了完整,我们还要安装开发服务器(webpack-dev-server),不必每次修改都完整的打包、发布和测试。另外,还要安装清理插件(clean-webpack-plugin)。

npm i -D webpack-dev-server

webpack.config.js配置

const webpack = require('webpack')

module.exports =  {
  /* ... */
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    static: path.resolve(__dirname, './dist'),
    open: true,
    compress: true,
    hot: true,
    port: 8080,
  },

  plugins: [
    /* ... */
    // Only update what has changed on hot reload
    new webpack.HotModuleReplacementPlugin(),
  ],
})

package.json

"scripts": {
  "start": "webpack serve"
}

Clean webpack plugin

npm install clean-webpack-plugin --save-dev

webpack.config .js

...
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  /* ... */

  plugins: [
    /* ... */
    new CleanWebpackPlugin(),  ],
}

Github源码

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK