>웹 프론트엔드 >JS 튜토리얼 >webpack+express 다중 페이지 사이트 개발 사례에 대한 자세한 설명

webpack+express 다중 페이지 사이트 개발 사례에 대한 자세한 설명

小云云
小云云원래의
2017-12-23 15:11:471552검색

webpack 입문용 튜토리얼을 공부한 후, 다양한 리소스의 종속성 로딩 및 패키징 문제를 해결할 수 있는 webpack+react, webpack+vue 등과 같은 단일 페이지 애플리케이션에 맞게 맞춤 제작될 수 있다는 느낌이 들었습니다. . CSS도 js에 패키지되어 있으며 dom 문서에 동적으로 추가됩니다. 이번 글은 주로 webpack+express 다중 페이지 사이트 개발에 대한 자세한 설명을 소개하는데, 모든 분들께 도움이 되었으면 좋겠습니다.

그렇다면 여러 페이지로 구성된 일반 웹사이트를 원한다면 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模板
  - node_modules    #所使用的nodejs模块
  - public            #express静态资源文件
    - dist            #webpack编译打包输出目录,无需建立目录可由webpack根据配置自动生成
      + css        
      + js
    + img      #图片资源
  + view            #express静态资源文件(webpack编译打包输出view目录)
  package.json      #项目配置
  webpack.config.js  #webpack配置

Development

페이지는 src/js/page 디렉터리에 index.js 파일을 생성하고 src/view 디렉터리에 index.html 파일을 생성합니다. js 항목은 템플릿 파일 이름에 해당합니다.

index.html의 내용은 다음과 같습니다.


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>首页</title>
  <!--
    描述:head中无需再引入css以及facicon,webpack将根据入口JS文件的要求自动实现按需加载或者生成style标签
  -->
</head>
<body>
  <!--
    描述:body中同样无需单独引入JS文件,webpack会根据入口JS文件自动实现按需加载或者生成script标签,还可以生成对应的hash值
  -->
</body>
</html>

는 매우 간단한 HTML 템플릿입니다. CSS나 JS를 도입하지 않고 webpack 패키징을 통해 자동으로 도입할 수 있습니다.

index.js 내용은 다음과 같습니다.


//引入css
require("../../css/lib/base.css");
require("../../css/page/index.scss");
$(&#39;body&#39;).append(&#39;<p class="text">index</p>&#39;);

page1.html:


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

page1.js:


//引入css
require("../../css/lib/base.css");
require("../../css/page/page1.less");
$(&#39;body&#39;).html(&#39;page1&#39;);

webpack 구성(저는 Express 프레임워크를 사용하고 다른 것들은 개인적인 필요에 따라 구성합니다. )


var path = require(&#39;path&#39;);
var webpack = require(&#39;webpack&#39;);
/*
extract-text-webpack-plugin插件,
有了它就可以将你的样式提取到单独的css文件里,
妈妈再也不用担心样式会被打包到js文件里了。
 */
var ExtractTextPlugin = require(&#39;extract-text-webpack-plugin&#39;);
/*
html-webpack-plugin插件,重中之重,webpack中生成HTML的插件,
具体可以去这里查看https://www.npmjs.com/package/html-webpack-plugin
 */
var HtmlWebpackPlugin = require(&#39;html-webpack-plugin&#39;);

module.exports = {
  entry: { //配置入口文件,有几个写几个
    index: &#39;./src/js/page/index.js&#39;,
    page1: &#39;./src/js/page/page1.js&#39;
  },
  output: { 
    path: path.join(__dirname, &#39;./public/dist/&#39;), //输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它
    publicPath: &#39;/dist/&#39;,        //模板、样式、脚本、图片等资源对应的server上的路径
    filename: &#39;js/[name].js&#39;,      //每个页面对应的主js的生成配置
    chunkFilename: &#39;js/[id].chunk.js&#39;  //chunk生成的配置
  },
  module: {
    loaders: [ //加载器,关于各个加载器的参数配置,可自行搜索之。
      {
        test: /\.css$/,
        //配置css的抽取器、加载器。&#39;-loader&#39;可以省去
        loader: ExtractTextPlugin.extract(&#39;style-loader&#39;, &#39;css-loader&#39;) 
      }, {
        test: /\.less$/,
        //配置less的抽取器、加载器。中间!有必要解释一下,
        //根据从右到左的顺序依次调用less、css加载器,前一个的输出是后一个的输入
        //你也可以开发自己的loader哟。有关loader的写法可自行谷歌之。
        loader: ExtractTextPlugin.extract(&#39;css!less&#39;)
      }, {
        test: /\.scss$/,
        //配置scss的抽取器、加载器。中间!有必要解释一下,
        //根据从右到左的顺序依次调用scss、css加载器,前一个的输出是后一个的输入
        //你也可以开发自己的loader哟。有关loader的写法可自行谷歌之。
        loader: ExtractTextPlugin.extract(&#39;css!scss&#39;)
      }, {
        //html模板加载器,可以处理引用的静态资源,默认配置参数attrs=img:src,处理图片的src引用的资源
        //比如你配置,attrs=img:src img:src就可以一并处理src引用的资源了,就像下面这样
        test: /\.html$/,
        loader: "html?attrs=img:src img:src"
      }, {
        //文件加载器,处理文件静态资源
        test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: &#39;file-loader?name=./fonts/[name].[ext]&#39;
      }, {
        //图片加载器,雷同file-loader,更适合图片,可以将较小的图片转成base64,减少http请求
        //如下配置,将小于8192byte的图片转成base64码
        test: /\.(png|jpg|gif)$/,
        loader: &#39;url-loader?limit=8192&name=./img/[hash].[ext]&#39;
      }
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({ //加载jq
      $: &#39;jquery&#39;
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: &#39;commons&#39;, // 将公共模块提取,生成名为`commons`的chunk
      chunks: [&#39;index&#39;,&#39;page1&#39;], //提取哪些模块共有的部分
      minChunks: 2 // 提取至少2个模块共有的部分
    }),
    new ExtractTextPlugin(&#39;css/[name].css&#39;), //单独使用link标签加载css并设置路径,相对于output配置中的publickPath
    
    //HtmlWebpackPlugin,模板生成相关的配置,每个对于一个页面的配置,有几个写几个
    new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML
      favicon: &#39;./src/favicon.ico&#39;, //favicon路径,通过webpack引入同时可以生成hash值
      filename: &#39;../../views/index.html&#39;, //生成的html存放路径,相对于path
      template: &#39;./src/template/index.html&#39;, //html模板路径
      inject: &#39;body&#39;, //js插入的位置,true/&#39;head&#39;/&#39;body&#39;/false
      hash: true, //为静态资源生成hash值
      chunks: [&#39;commons&#39;, &#39;index&#39;],//需要引入的chunk,不配置就会引入所有页面的资源
      minify: { //压缩HTML文件  
        removeComments: true, //移除HTML中的注释
        collapseWhitespace: false //删除空白符与换行符
      }
    }),
    new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML
      favicon: &#39;./src/favicon.ico&#39;, //favicon路径,通过webpack引入同时可以生成hash值
      filename: &#39;../../views/page1.html&#39;, //生成的html存放路径,相对于path
      template: &#39;./src/template/page1.html&#39;, //html模板路径
      inject: true, //js插入的位置,true/&#39;head&#39;/&#39;body&#39;/false
      hash: true, //为静态资源生成hash值
      chunks: [&#39;commons&#39;, &#39;list&#39;],//需要引入的chunk,不配置就会引入所有页面的资源
      minify: { //压缩HTML文件  
        removeComments: true, //移除HTML中的注释
        collapseWhitespace: false //删除空白符与换行符
      }
    })

    // new webpack.HotModuleReplacementPlugin() //热加载
  ],
  //使用webpack-dev-server,提高开发效率
  // devServer: {
  //   contentBase: &#39;./&#39;,
  //   host: &#39;localhost&#39;,
  //   port: 9090, //默认8080
  //   inline: true, //可以监控js变化
  //   hot: true, //热启动
  // }
};

자, 위 설정을 모두 마친 후 webpackpackage 명령어를 실행하면 프로젝트 패키징이 완성됩니다.


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 hidden modules
Child html-webpack-plugin for "../../view/page1.html":
    + 1 hidden modules
Child html-webpack-plugin for "../../view/index.html":
    + 1 hidden modules
Child extract-text-webpack-plugin:
    + 2 hidden modules
Child extract-text-webpack-plugin:
    + 2 hidden modules
Child extract-text-webpack-plugin:
    + 2 hidden modules

이때 생성된 index.html 파일을 보려면 views 디렉터리로 이동하면 다음과 같습니다.


<!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>

원본 템플릿의 내용을 유지하는 것 외에도 생성된 파일은 엔트리 파일 인덱스도 사용합니다. .js 정의를 위해 자동 추가를 위해서는 파비콘뿐만 아니라 CSS, JS 파일 도입이 필요하며 해당 해시 값도 추가됩니다.

두 가지 질문

  1. webpack은 어떻게 항목 파일을 자동으로 검색하고 해당 템플릿을 구성합니까?

  2. 스타일 및 스크립트 자동 도입 문제를 직접 처리하는 방법


var path = require(&#39;path&#39;);
var webpack = require(&#39;webpack&#39;);
var glob = require(&#39;glob&#39;);
/*
extract-text-webpack-plugin插件,
有了它就可以将你的样式提取到单独的css文件里,
妈妈再也不用担心样式会被打包到js文件里了。
 */
var ExtractTextPlugin = require(&#39;extract-text-webpack-plugin&#39;);
/*
html-webpack-plugin插件,重中之重,webpack中生成HTML的插件,
具体可以去这里查看https://www.npmjs.com/package/html-webpack-plugin
 */
var HtmlWebpackPlugin = require(&#39;html-webpack-plugin&#39;);
/**
 *将公共模块提取,生成名为`commons`的chunk
 */
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
//压缩
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

//判断开发模式
var debug = process.env.NODE_ENV !== &#39;production&#39;;
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(&#39;^&#39; + pathDir), &#39;&#39;) : pathname;
    entries[pathname] = [&#39;./&#39; + entry]; //这是在osx系统下这样写 win7 entries[basename]
  }
  console.log(entries);
  return entries;
}

//入口(通过getEntry方法得到所有的页面入口文件)
var entries = getEntry(&#39;src/js/page/**/*.js&#39;, &#39;src/js/page/&#39;);
//提取哪些模块共有的部分从entries里面获得文件名称
var chunks = Object.keys(entries);
//模板页面(通过getEntry方法得到所有的模板页面)
var pages = Object.keys(getEntry(&#39;src/template/**/*.html&#39;, &#39;src/template/&#39;));

console.log(pages)

var config = {
  entry: entries,
  output: {
    path: path.join(__dirname, &#39;./public/dist/&#39;),//输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它
    publicPath: &#39;/dist/&#39;,        //模板、样式、脚本、图片等资源对应的server上的路径
    filename: &#39;js/[name].js&#39;,      //每个页面对应的主js的生成配置
    chunkFilename: &#39;js/[id].chunk.js?[chunkhash]&#39;  //chunk生成的配置
  },
  module: {
    loaders: [ //加载器
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract(&#39;style&#39;, &#39;css&#39;)
      }, {
        test: /\.less$/,
        loader: ExtractTextPlugin.extract(&#39;css!less&#39;)
      }, {
        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: &#39;file-loader?name=fonts/[name].[ext]&#39;
      }, {
        test: /\.(png|jpe?g|gif)$/,
        loader: &#39;url-loader?limit=8192&name=imgs/[name]-[hash].[ext]&#39;
      }
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({ //加载jq
      $: &#39;jquery&#39;
    }),
    new CommonsChunkPlugin({
      name: &#39;commons&#39;, // 将公共模块提取,生成名为`commons`的chunk
      chunks: chunks,
      minChunks: chunks.length // 提取所有entry共同依赖的模块
    }),
    new ExtractTextPlugin(&#39;css/[name].css&#39;), //单独使用link标签加载css并设置路径,相对于output配置中的publickPath
    debug ? function() {} : new UglifyJsPlugin({ //压缩代码
      compress: {
        warnings: false
      },
      except: [&#39;$super&#39;, &#39;$&#39;, &#39;exports&#39;, &#39;require&#39;] //排除关键字
    }),
  ]
};

pages.forEach(function(pathname) {
  var conf = {
    filename: &#39;../../views/&#39; + pathname + &#39;.html&#39;, //生成的html存放路径,相对于path
    template: &#39;src/template/&#39; + pathname + &#39;.html&#39;, //html模板路径
    inject: false, //js插入的位置,true/&#39;head&#39;/&#39;body&#39;/false
    /*
    * 压缩这块,调用了html-minify,会导致压缩时候的很多html语法检查问题,
    * 如在html标签属性上使用{{...}}表达式,所以很多情况下并不需要在此配置压缩项,
    * 另外,UglifyJsPlugin会在压缩代码的时候连同html一起压缩。
    * 为避免压缩html,需要在html-loader上配置&#39;html?-minimize&#39;,见loaders中html-loader的配置。
     */
    // minify: { //压缩HTML文件
    // removeComments: true, //移除HTML中的注释
    // collapseWhitespace: false //删除空白符与换行符
    // }
  };
  if (pathname in config.entry) {
    favicon: &#39;./src/favicon.ico&#39;, //favicon路径,通过webpack引入同时可以生成hash值
    conf.inject = &#39;body&#39;;
    conf.chunks = [&#39;commons&#39;, pathname];
    conf.hash = true;
  }
  config.plugins.push(new HtmlWebpackPlugin(conf));
});
module.exports = config;

The 아래 코드와 위 코드는 거의 동일하지만 본질적인 차이점은 관련된 모든 파일을 메소드를 통해 객체에 넣어 자동 도입 효과를 완성한다는 점입니다!

위 내용은 모두 mac osx 시스템의 구성이며 win7 경로는 다를 수 있습니다.

glob: 여기에서의 분석은 다릅니다.

하지만 최종 요구 사항


entries:
 {
 index: [ &#39;./src/template/index.js&#39; ],
 page1: [ &#39;./src/template/page1.js&#39; ]
 }

pages:
 [ &#39;index&#39;, &#39;page1&#39; ]

은 다음 구성을 기반으로 해야 합니다. 개인용 컴퓨터 그에 따라 변경하십시오.

관련 권장사항:

웹팩 프론트엔드 엔지니어링을 기반으로 한 다중 페이지 사이트 개발 (2)_html/css_WEB-ITnose

Node.js 및 Express 시작에 대한 간략한 소개(그림 및 텍스트)

webpack 학습 튜토리얼의 프론트엔드 성능 최적화 요약

위 내용은 webpack+express 다중 페이지 사이트 개발 사례에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.