English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

شرح تطوير موقع متعدد الصفحات باستخدام webpack + express

بعد دراسة دروس webpack المتقدمة، يبدو أن ذلك مصمم خصيصًا للعناصر الواحدة، مثل webpack+react،webpack+vue،وهي يمكن حل مشاكل تحميل وتغليف الموارد. حتى css يمكن تضمينها في js وتحديدًا إضافة إلى مستند DOM بشكل ديناميكي.

إذا أردنا موقع ويب عادي متعدد الصفحات، وإزالة css، وتحميل js كنموذج؟

عنوان المشروع:webpackDemo_jb51.rar

بدء المشروع، تثبيت الاعتماد

package.json

"devDependencies": {
  "css-loader": "^0.23.1",
  "extract-text-webpack-plugin": "^1.0.1",
  "file-loader": "^0.8.5",
  "html-loader": "^0.4.3",
  "html-webpack-plugin": "^2.9.0",
  "jquery": "^1.12.0",
  "less": "^2.6.0",
  "less-loader": "^2.2.2",
  "sass-loader": "^4.0.2",
  "style-loader": "^0.13.0",
  "url-loader": "^0.5.7",
  "webpack": "^1.12.13",
  "webpack-dev-server": "^1.14.1"
}

تركيبة الدليل (استخدمت إطار العمل express، الأخرى حسب الحاجة الشخصية)

- webpackDemo
  - src        #代码开发目录
    - css      #css目录,按照页面(模块)、通用、第三方三个级别进行组织
      + page
      + common
      + lib
    - js       #JS脚本,按照page、components进行组织
      + page
      + components
    + template      #HTML template
  - node_modules    #used nodejs modules
  - public            #express static resource files
    - dist            #webpack compiled and packaged output directory, no need to create a directory, which can be automatically generated by webpack according to the configuration
      + css        
      + js
    + img      #image resources
  + view            #express static resource files (webpack compiled and packaged output to the view directory)
  package.json      #project configuration
  webpack.config.js  #webpack configuration

Developing pages

Create an index.js file under the src/js/page directory, and create an index.html file under the src/view directory. The entry JS and template file names correspond.

The content of index.html is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>الصفحة الرئيسية</title>
  <!--
    Description: No need to introduce CSS and facicon in the head, webpack will automatically implement lazy loading or generate style tags according to the requirements of the entry JS file
  -->
</head>
<body>
  <!--
    Description: No need to introduce JS files separately in the body, webpack will automatically implement lazy loading or generate script tags according to the entry JS file, and can also generate corresponding hash values
  -->
</body>
</html>

It is just such a simple HTML template, do not introduce any CSS and JS, and it can be automatically introduced through webpack packaging.

The content of index.js is as follows:

// Import css
require("../../css/lib/base.css");
require("../../css/page/index.scss");
$('body').append('<p class="text">index</p>');

page1.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>page1</title>
</head>
<body>
</body>
</html>

page1.js:

// Import css
require("../../css/lib/base.css");
require("../../css/page/page1.less");
$('body').html('page1');

webpack configuration (I use the express framework, others according to personal needs)

var path = require('path');
var webpack = require('webpack');
/*
ملحق extract-text-webpack-plugin
معه يمكنك استخراج أنماطك إلى ملفات CSS منفصلة
لم يعد عليك أن تقلق بعد الآن بأن الأنماط ستُدمج في ملفات JavaScript
 */
var ExtractTextPlugin = require('extract-text-webpack-plugin');
/*
ملحق html-webpack-plugin، مهم جدًا، ملحق إنشاء HTML في webpack
يمكنك التحقق من هنا https://www.npmjs.com/package/html-webpack-plugin
 */
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: { // Configure the entry file, write as many as needed
    index: './src/js/page/index.js'
    page1: './src/js/page/page1.js'
  },
  output: { 
    path: path.join(__dirname, './public/dist/'), //输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它
    publicPath: '/dist/',        //模板、样式、脚本、图片等资源对应的server上的路径
    filename: 'js/[name].js',      //每个页面对应的主js的生成配置
    chunkFilename: 'js/[id].chunk.js'  //chunk生成的配置
  },
  module: {
    loaders: [ //加载器,关于各个加载器的参数配置,可自行搜索之。
      {
        test: /\.css$/,
        //配置css的抽取器、加载器。'-loader'可以省去
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader') 
      }, {
        test: /\.less$/,
        //配置less的抽取器、加载器。中间!有必要解释一下,
        //根据从右到左的顺序依次调用less、css加载器,前一个的输出是后一个的输入
        //你也可以开发自己的loader哟。有关loader的写法可自行谷歌之。
        loader: ExtractTextPlugin.extract('css!less')
      }, {
        test: /\.scss$/
        //配置scss的抽取器、加载器。中间!有必要解释一下,
        //根据从右到左的顺序依次调用scss、css加载器,前一个的输出是后一个的输入
        //你也可以开发自己的loader哟。有关loader的写法可自行谷歌之。
        loader: ExtractTextPlugin.extract('css!scss')
      }, {
        //html模板加载器,可以处理引用的静态资源,默认配置参数attrs=img:src,处理图片的src引用的资源
        //比如你配置,attrs=img:src img:data-src就可以一并处理data-src引用的资源了,就像下面这样
        test: /\.html$/,
        loader: "html?attrs=img:src img:data-src"
      }, {
        //文件加载器,处理文件静态资源
        test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'file-loader?name=./fonts/[name].[ext]'
      }, {
        //图片加载器,雷同file-loader,更适合图片,可以将较小的图片转成base64,减少http请求
        //如下配置,将小于8192byte的图片转成base64码
        test: /\.(png|jpg|gif)$/
        loader: 'url-loader?limit=8192&name=./img/[hash].[ext]'
      }
    ])
  },
  plugins: [
    new webpack.ProvidePlugin({ // تحميل jq
      $: 'jquery'
    }),
    new webpack.optimize.CommonsChunkPlugin({}}
      name: 'commons', // استخراج الوحدات العامة، وإنشاء وحدة تسمى `commons`
      chunks: ['index','page1'], // استخراج الأجزاء المشتركة للمكونات
      minChunks: 2 // استخراج الأجزاء المشتركة لعدد لا يقل عن 2 المodule
    }),
    new ExtractTextPlugin('css/[name].css'), // استخدام علامة link منفصلة لتحميل CSS وضبط المسار، بالنسبة لمسار publickPath في تكوين output
    //HtmlWebpackPlugin، تكوينات الجيل المتعلقة بالقالب، لكل صفحة تكوين واحد، يكتب عدد تكوينات الصفحات
    new HtmlWebpackPlugin({ // إدراج css/js وما إلى ذلك بناءً على القالب لإنشاء HTML النهائي
      favicon: './src/favicon.ico', // مسار favicon، يتم استيراده من خلال webpack ويمكن توليد قيمة hash
      filename: '../../views/index.html', // مسار حفظ HTML المولد، بالنسبة لمسار
      template: './src/template/index.html', // مسار قالب HTML
      inject: 'body', // موقع إدراج الجافا سكربت، true/'head'/'body'/false
      hash: true, // توليد قيمة hash لل موارد الثابتة
      chunks: ['commons', 'index'],// المكونات التي يجب استيرادها، لا يتم استيراد جميع موارد الصفحات إذا لم يتم تكوينها
      minify: { // ضغط ملفات HTML  
        removeComments: true, // إزالة التعليقات من HTML
        collapseWhitespace: false // إزالة الرموز غير المهمة والسطور
      }
    }),
    new HtmlWebpackPlugin({ // إدراج css/js وما إلى ذلك بناءً على القالب لإنشاء HTML النهائي
      favicon: './src/favicon.ico', // مسار favicon، يتم استيراده من خلال webpack ويمكن توليد قيمة hash
      filename: '../../views/page1.html', // مسار حفظ HTML المولد، بالنسبة لمسار
      template: './src/template/page1.html', // مسار قالب HTML
      inject: true, // موقع إدراج الجافا سكربت، true/'head'/'body'/false
      hash: true, // توليد قيمة hash لل موارد الثابتة
      chunks: ['commons', 'list'],// المكونات التي يجب استيرادها، لا يتم استيراد جميع موارد الصفحات إذا لم يتم تكوينها
      minify: { // ضغط ملفات HTML  
        removeComments: true, // إزالة التعليقات من HTML
        collapseWhitespace: false // إزالة الرموز غير المهمة والسطور
      }
    })
    // new webpack.HotModuleReplacementPlugin() // التحميل الساخن
  ],
  // استخدم webpack-dev-server لتحسين كفاءة التطوير
  // devServer: {
  //   contentBase: './',
  //   host: 'localhost',
  //   port: 9090, // القيمة الافتراضية 8080
  //   inline: true, // يمكن مراقبة التغييرات في الجافا سكربت
  //   hot: true, //start hot
  // }
};

حسنًا، بعد إكمال هذه الإعدادات، اتبع أمر webpack packaging لإنهاء عملية تعبئة المشروع.

Hash: e6219853995506fd132a
Version: webpack 1.14.0
Time: 1338ms
        Asset    Size Chunks       Chunk Names
     js/index.js 457 bytes    0 [emitted] index
     js/page1.js 392 bytes    1 [emitted] page1
    js/commons.js   306 kB    2 [emitted] commons
    css/index.css  62 bytes    0 [emitted] index
    css/page1.css  62 bytes    1 [emitted] page1
   css/commons.css 803 bytes    2 [emitted] commons
     favicon.ico  1.15 kB     [emitted]
../../view/index.html 496 bytes     [emitted]
../../view/page1.html 499 bytes     [emitted]
  [0] ./src/js/page/index.js 170 bytes {0} [built]
  [0] ./src/js/page/page1.js 106 bytes {1} [built]
  + 7 modules not included
Child html-webpack-plugin for "../../view/page1.html":
    + 1 module not included
Child html-webpack-plugin for "../../view/index.html":
    + 1 module not included
Child extract-text-webpack-plugin:
    + 2 modules not included
Child extract-text-webpack-plugin:
    + 2 modules not included
Child extract-text-webpack-plugin:
    + 2 modules not included

في هذا الوقت، انتقل إلى مجلد views لرؤية ملف index.html المُنتج، مثلما يلي:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>الصفحة الرئيسية</title>  
<link rel="shortcut icon" href="/dist/favicon.ico" rel="external nofollow" ><link href="/dist/css/commons.css?e6219853995506fd132a" rel="external nofollow" rel="stylesheet"><link href="/dist/css/index.css?e6219853995506fd132a" rel="external nofollow" rel="stylesheet"></head>
<body>
  <script type="text/javascript" src="/dist/js/commons.js?e6219853995506fd132a"></script><script type="text/javascript" src="/dist/js/index.js?e6219853995506fd132a"></script></body>
</html>

يمكنك رؤية أن الملفات المولدة، بالإضافة إلى الحفاظ على محتويات النمط الأصلي، تضيف تلقائيًا ملفات CSS وJavaScript المطلوبة، بالإضافة إلى أيقونة الموقع، وتضيف أيضًا قيم hash المناسبة

مشكلتان

  1. كيف يكتشف webpack ملفات entry تلقائيًا ويقوم بضبط التكوينات النمطية المناسبة
  2. كيفية التعامل المباشر مع مشكلة التضمين التلقائي للأنماط والسكربت
var path = require('path');
var webpack = require('webpack');
var glob = require('glob');
/*
ملحق extract-text-webpack-plugin
معه يمكنك استخراج أنماطك إلى ملفات CSS منفصلة
لم يعد عليك أن تقلق بعد الآن بأن الأنماط ستُدمج في ملفات JavaScript
 */
var ExtractTextPlugin = require('extract-text-webpack-plugin');
/*
ملحق html-webpack-plugin، مهم جدًا، ملحق إنشاء HTML في webpack
يمكنك التحقق من هنا https://www.npmjs.com/package/html-webpack-plugin
 */
var HtmlWebpackPlugin = require('html-webpack-plugin');
/**
 * استخراج المكونات المشتركة، لإنشاء chunk يُدعى `commons`
 */
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
// التكبيل
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
// التحقق من وضع التطوير
var debug = process.env.NODE_ENV !== 'production';
var getEntry = function(globPath, pathDir) {
  var files = glob.sync(globPath);
  var entries = {},
    entry, dirname, basename, pathname, extname;
  for (var i = 0; i < files.length; i++) {
    entry = files[i];
    dirname = path.dirname(entry);  // مجلد الملف
    extname = path.extname(entry);  // اسم التوسع
    basename = path.basename(entry, extname); // اسم الملف
    pathname = path.join(dirname, basename);
    pathname = pathDir ? pathname.replace(new RegExp('^' + pathDir), '') : pathname;
    entries[pathname] = ['./' + entry]; // بهذا الشكل في نظام osx entries[basename] في win7
  }
  console.log(entries);
  return entries;
}
// مدخل (من خلال طريقة getEntry للحصول على جميع ملفات الدخول للصفحات)
var entries = getEntry('src/js/page/**/*.js', 'src/js/page/');
//提取哪些模块共有的部分从entries里面获得文件名称
var chunks = Object.keys(entries);
//模板页面(通过getEntry方法得到所有的模板页面)
var pages = Object.keys(getEntry('src/template/**/*.html', 'src/template/'));
console.log(pages)
var config = {
  entry: entries,
  output: {
    path: path.join(__dirname, './public/dist/'),//输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它
    publicPath: '/dist/',        //模板、样式、脚本、图片等资源对应的server上的路径
    filename: 'js/[name].js',      //每个页面对应的主js的生成配置
    chunkFilename: 'js/[id].chunk.js?[chunkhash]'  //chunk生成的配置
  },
  module: {
    loaders: [ //加载器
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style', 'css')
      }, {
        test: /\.less$/,
        loader: ExtractTextPlugin.extract('css!less')
      }, {
        test: /\.html$/,
        loader: "html?-minimize"  //避免压缩html,https://github.com/webpack/html-loader/issues/50
      }, {
        test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'file-loader?name=fonts/[name].[ext]'
      }, {
        test: /\.(png|jpe?g|gif)$/,
        loader: 'url-loader?limit=8192&name=imgs/[name]-[hash].[ext]'
      }
    ])
  },
  plugins: [
    new webpack.ProvidePlugin({ // تحميل jq
      $: 'jquery'
    }),
    new CommonsChunkPlugin({
      name: 'commons', // استخراج الوحدات العامة، وإنشاء وحدة تسمى `commons`
      chunks: chunks,
      minChunks: chunks.length // استخراج جميع الوحدات المشتركة بين الدخول
    }),
    new ExtractTextPlugin('css/[name].css'), // استخدام علامة link منفصلة لتحميل CSS وضبط المسار، بالنسبة لمسار publickPath في تكوين output
    debug ? function() {} : new UglifyJsPlugin({ // تقليل الكود
      compress: {
        warnings: false
      },
      except: ['$super', '$', 'exports', 'require'] // استثناء الكلمات المفتاحية
    }),
  ])
};
pages.forEach(function(pathname) {
  var conf = {
    filename: '../../views/' + pathname + '.html', // مسار حفظ HTML المولد، بالنسبة لمسار path
    template: 'src/template/' + pathname + '.html', // مسار نموذج HTML
    inject: false, // موقع إدراج JS، true/'head'/'body'/false
    /*
    * عند تقليل هذا الجزء، سيؤدي استدعاء html-minify إلى مشاكل في قواعد اللغة لـ HTML أثناء التقليل،
    * إذا كنت تستخدم تعبيرات {{...}} في خصائص علامات HTML، لذا في العديد من الحالات لا تحتاج إلى تكوين تقليل الحجم هنا،
    * بالإضافة إلى ذلك، سيتضمن UglifyJsPlugin تقليل حجم الكود مع HTML عند التقليل.
    * من أجل تجنب تقليل حجم HTML، يجب تكوين 'html?-minimize' في html-loader، انظر تكوين html-loader في loaders.
     */
    // minify: { // تقليل حجم ملف HTML
    // removeComments: true, // إزالة التعليقات في HTML
    // collapseWhitespace: false // حذف الفواصل البيانية والعناصر المفردة
    // }
  };
  if (pathname in config.entry) {
    favicon: './src/favicon.ico', // مسار favicon، يتم استيراده من خلال webpack ويمكن توليد قيمة hash
    conf.inject = 'body';
    conf.chunks = ['commons', pathname];
    conf.hash = true;
  }
  config.plugins.push(new HtmlWebpackPlugin(conf));
});
module.exports = config;  

كود التالي مشابه لما سبق، الفرق الأساسي هو أننا نضع جميع الملفات ذات الصلة في مكتبة واحدة من خلال طريقة واحدة ونكمل تأثير التضمين التلقائي!

الإعدادات المذكورة أعلاه هي لـ نظام التشغيل mac osx، قد تكون المسارات المختلفة في win7

glob: يتم تحليلها بشكل مختلف هنا:

لكن يجب أن تكون النهاية

entries:
 {
 index: ['./src/template/index.js'],
 page1: ['./src/template/page1.js']
 }
pages:
 ['index', 'page1']

يجب تعديلها بناءً على تكوين جهاز الكمبيوتر الشخصي

هذا هو نهاية محتوى هذا المقال، نأمل أن يكون قد ساعدكم في تعلم، ونأمل أيضًا أن تدعموا وتعززوا دروس النطق.

البيان: محتوى هذا المقال تم جمعه من الإنترنت، ويتمتع المالك الأصلي بحقوق الطبع والنشر، تم جمع المحتوى من قبل المستخدمين على الإنترنت وتم تحميله بشكل مستقل، هذا الموقع لا يمتلك حقوق الملكية، لم يتم تعديل المحتوى بشكل إنساني، ولا يتحمل أي مسؤولية قانونية. إذا كنت قد وجدت محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' ب '@') للإبلاغ، وتقديم الدليل المتعلق، وإذا تم التحقق من ذلك، فإن هذا الموقع سيزيل محتوى يشتبه في انتهاك حقوق النسخ فورًا.

أفضل الأشياء التي قد تفضلها