webpack 的打包依赖于它的一个重要配置文件 webpack.config.JS, 在这个配置文件中就可以指定所有在源代码编译过程中的工作了, 就一个配置就可以与冗长的 Gruntfile 或者 Gulpfile 说再见了.
一个完整的工程项目中的 webpack 的配置远远没有这么简单, 随着工程的构建要求的增加, webpack.config.JS 内的配置项目也会随之增加, webpack 还有许许多多的选项提供给我们进行灵活配置, 它只是一个构建工具, 我们只需要了解在 vue 项目中它基本能为我们做到的工作, 最小化的配置是如何的就足够了, 在以后需要对它进行扩展与优化时, 带着问题去查官方文档也是非常容易的事.
● 样式表引用
某些页面或者组件可能具有特定的样式定义, 这些样式对于其他页面来说是冗余的, 我们只希望这些组件在应用时才自动加载这些特定的样式, 此时用 webpack 我们就能在源代码中加入以下代码来动态加载 CSS:
- import Vue from 'vue'
- // ... 省略
- // 引用指定的样式源文件
- import './App/assets/Less/dark.Less'
- export default {
- // ... 省略
- }
此时我们只需要在 webpack 的配置中加入 Less-loader, 那么 webpack 在打包的时候就会自动将 Less 转换为 CSS, 并将 CSS 的动态代码生成到 JS 文件中. 当 Vue 组件被加载到页面并实例化后, 将在 DOM 内插入这个特定的行内样式 < style > 以实现动态样式的应用.
对于 *.CSS 文件同样也是适用的, 例如导入某个第三方库中必需的样式表:
import 'uikit/dist/CSS/components/tabs.CSS'
● 字体的引用
假设在 dark.Less 内加入对自定义字体文件的样式定义:
- @font-face {
- font-family: 'Darkenstone';
- src: url('./Darkenstone.eot');
- src: url('./Darkenstone.eot?#iefix') format('embedded-opentype'),
- url('./Darkenstone.woff2') format('woff2'),
- url('./Darkenstone.woff') format('woff'),
- url('./Darkenstone.ttf') format('truetype'),
- url('./Darkenstone.svg#Darkenstone') format('svg');
- font-weight: normal;
- font-style: normal;
- }
- .header{
- display: flex;
- flex-flow: row nowrap;
- &> h1 {
- font: 16pt 'Darkenstone';
- }
- }
这里. header>h1 指定了一个 Darkenstone 的自定义字体, 这个字体浏览器一定是不能识别的, 以前我们在样式表中先定义这个字体样式并指定加载位置 (如上文 @font-face 的定义), 然后在页面中引用这个样式表, 这是多么麻烦的一件事, 不是吗?
如果用了 webpack 后, 我们只是在配置文件内加入了一个 url-loader:
- {
- test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- loader: 'url'
- }
我们并不需要在源代码中做任何改变, 因为之前已经引用过样式表 dark.Less, 而字体是在样式表中的, webpack 将在打包的时候为我们识别并在代码中引入字体的动态加载. 这样一来极大地解决了我们对资源引用的依赖问题!
vue-cli 的 webpack 模板已经为我们配置好了绝大多数常用的 loader, 在实际运用中我们只需要了解它们是怎么来的, 应该怎么用, 需要的时候如何修改就够了.
● 用别名取代路径引用
在项目开发过程中有可能有许多包是没有放在 NPM 上的, 有一些较老的可能还依然只存在于 bower 上, 某些甚至在 bower 与 NPM 上都找不到, 而不得不通过下载的方式在项目内引用, 这样一来我们的代码可能通过 require 就得在代码内引用一段很长的文件路径, 如下所示
import Selector from '../../bower_components/Bootstrap-select/dist/JS/select'
这种包的引用方式明显违反了 CommonJS 的编程规范, 对于这些长路径, 甚至还具有 "../.." 这些相对路径搜索的定义, 我们可以通过 webpack 的 resolve 配置项来解决. 就以 select 这个组件为例, 在 webpack.base.config.JS 中加入以下的这个别名的定义:
- module.exports = {
- entry:{ ... },
- output: { ... },
- module:{ ... },
- resolve: {
- extensions:['','.JS'],
- alias:{ // 别名
- 'bs-select':'bower_components/Bootstrap-select/dist/JS/select.JS'
- }
- }
- }
有了这个定义以后, 我们就可以将上面那个长引用改为下面的写法:
import Selector from 'bs-select';
绝对不要让路径引用进入到我们的代码, 因为这是代码的 "癌症", 一旦开始植入并生长起来, 以前的代码将难以维护!
● 配置多入口程序
多数情况下我们的程序入口不单单只有一个, 举一个最简单的例子, 前台提供给最终用户使用 (http://www.domain.com/index), 后台提供给登录用户使用 (http://www.domain.com/admin/), 那么自然需要多个与 main.JS 类似的程序入口了.
首先在 build/webpack.base.conf.JS 配置文件中的 entry 配置属性上加上新的入口文件:
- module.exports = {
- entry: {
- App: './src/main.JS',
- admin : './src/admin-main.JS'
- },
- // ... 省略
- }
这是用于告诉 webpack 哪几个是入口文件, 这些文件需要被生成到启动页的 < script > 内.
vue-cli 的 webpack 模板使用 htmlWebpackPlugin 插件, 生成 HTML 入口页面并自动将生成后的 JS 文件和 CSS 文件的引用地址写入到页内的 < script > 中.
这里就需要在 build/webpack.dev.config.JS 文件内的 plugins 配置项内多配置一个 HtmlWebpackPlugin 插件, 用于生成 admin.HTML 入口页.
- plugins:[
- // ... 省略
- // 这是原有的配置项, 用于匹配注入 App.JS 的输出脚本
- new HtmlWebpackPlugin({
- filename: process.env.NODE_ENV === 'testing'
- ? 'index.HTML'
- : config.build.index,
- template: 'index.HTML',
- chunks: ['App'], // 与原配置的不同的是要用 chunks 指定对应的 entry
- inject: true,
- minify: {
- removeComments: true,
- collapseWhitespace: true,
- removeAttributeQuotes: true
- },
- chunksSortMode: 'dependency'
- }),
- // 这是新增项, 用于匹配注入 admin.JS 的输出脚本
- new HtmlWebpackPlugin({
- filename: process.env.NODE_ENV === 'testing'
- ? 'admin.HTML'
- : config.build.admin,
- template: 'index.HTML',
- chunks: ['admin'],
- inject: true,
- minify: {
- removeComments: true,
- collapseWhitespace: true,
- removeAttributeQuotes: true
- },
- chunksSortMode: 'dependency'
- }),
- ]
需要强调一点的是, 这里的 HtmlWebpackPlugin 配置必须用 chunks 指定在上文 entry 内对应的入口文件的别名.
关于 HtmlWebpackPlugin 更多配置内容可以参考: https://GitHub.com/kangax/HTML-minifier#options-quick-reference.
还有就是得将同样的配置加入到生产环境专用的 webpack 配置文件 webpack.prod.conf.JS 中, 否则当我们运行 NPM run build 时是不会输出 admin.JS 和 admin.HTML 这两个入口文件的 (由于配置内容相同这里就不再重复了).
最后, 如果使用了 vue-router 就得对 connect-history-API-fallback 插件的配置进行修改, 否则原有的默认配置只会将所有的请求转发给 index.HTML, 这样就会导致 History API 没有办法正确地将请求指向 admin.HTML, 导致热加载失败, 具体做法如下所述.
打开 dev-server.JS 文件, 将 App.use(require('connect-history-API-fallback')()) 配置改为以下的方式:
- // handle fallback for HTML5 history API
- var history = require('connect-history-API-fallback')
- // App.use(require('connect-history-API-fallback')())
- App.use(history({
- rewrites: [
- { from: /^\/admin\/.*$/, to: '/admin.HTML' }
- ]
- }));
新入口需要有明确区分的路由规则, 否则还是会产生热加载失败的情况, 这样就非常不便于开发了.
来源: https://www.cnblogs.com/yinn/p/9720177.html