从0到上线开发企业级电商项目_前端_09_webpack对脚本和样式的处理
一、概要
通过阅读本文你可以解决以下几个问题:
1.对脚本的处理
(1)JS用什么loader来加载?
(2)官方文档上的例子entry只有一个js,我们有多个怎么办
(3)output里要分文件夹存放目标文件,怎么设置?
(4)jQuery引入方法?
(5)想提取出程序里的公共模块应该怎么处理?
2.对样式的处理
(1)样式用什么loader?
(2)webpack打包的css怎么独立成单独的文件
接下来我们就在实际操作中解决这些问题,项目的开发目录构架请参考之前文章,我是在已完成之前工作的情况下进行操作的,如果有自己的项目,可以通过阅读本文中的方法来做参考。在开发之前我们现在sublime安装一个插件,fileheader,这个插件的作用是在开始之前加一些说明,比如创建时间作者之类的。
现在让我们开始。
首先对webpack的配置文件进行改造成
var config = { entry: './src/page/index/index.js', output: { path: './dist', filename: 'app.js' } }; module.exports = config;
二、对js的处理
1.js用什么来加载 ?
官方提供了两种方法,一是webpack本身就可以支持js加载,另一种是Babel来加载再用polifile来做兼容性适配,但是第二种方法不能兼容IE8,所以这里我们采用webpack本身对js的加载器,即我们并不需要安装js的loader。
2.js的多入口处理方法 ?
entry目前是个字符串,我们将其修改成一个对象,地址是一个数组的方式来解决这个问题,这在webpack中是支持的。
entry: { 'index' : ['./src/page/index/index.js'], 'login' : ['./src/page/login/index.js'], }
然后在page里面建立一个login里面包含一个index.js,
用一个标记性的字符串,来测试刚才的结果
console.log('hello login');
同样,把之前的index文件夹下的indes.js也改掉
console.log('hello index');
之前的cats.js之后不会用了可以删除了。
使用webpack看到打包成功
打包完成后进入app.js看到了hello login,但是没有看到hello index,说明index没有进来,
这个的原因是在webpack.config.js文件中虽然有了两个entry但是output只有一个,这就出现了第三个问题。
3.如何配置输出文件 ?
进入webpack.config.js将output改为
output: { path: './dist', filename: 'js/[name].js' }
[name]是filename里支持的一个方法,可以按照源文件名字打包。
可以看到dist文件夹里已经有我们想要的文件了
但是我们看到app.js还在这里,而我们的配置文件中现在并没有这项之前的配置了,这是webpack的一个问题,webpack在配置的时候不会清除掉之前打包的文件。
因此需要把dist文件夹删了重新打包。
实现了效果之后我们注意到了一个问题,我们在开发中是希望不同类型的文件在不同的文件夹下,接下来我们说说这一点要怎么做到。
4.分文件夹存放目标文件
在 filename 中是支持路径的因此我们修改配置加上路径。
output: { path: './dist', filename: 'js/[name].js' }
再执行webpack 我们看到之前的两个文件已经去到了dist下的js文件夹,完成了不同类型文件放置于不同文件夹的功能,这就是我们想要的。
5.jQuery该如何引用
1.测试
首先在view下建立一个测试用的index.html页面引入的 js
'use strict'; console.log('hello index'); var $ = require('jquery'); $('body').html('hello index~~~~~ !');
进入浏览器打开调试工具看到 hello index~~~~~ !,说明脚本已经引入进来了。
如果没有安装jQuery就安装一下,
2.安装jQuery
npm install jquery –save
现在使用一下jquery,page/index/index.js修改为
var $ = require('jquery'); $('body').html('HELLO INDEX'); console.log('hello index');
webpack一下,打开浏览器,刷新刚才的文件,可以看到HELLO INDEX就出来了,这就说明现在我们已经引入了jquery。
但是还有两个问题待解决,1.如果以这种方式引入,那么每个文件的前面都需要引入。2.有的jquery插件依赖的是全局的jquery对象,而以变量形式加载的jquery是没有办法放在插件里使用的。
3.引入jquery CDN
接下来我们开始解决这两个问题。
另一种方式是直接在脚本下面引入jquery CDN,可以在这里找www.bootcdn.cn/jquery/,这里我建议选择2.0以下的版本,因为2.0以上的版本对IE8不支持,这样就是一个全局的jquery了。另外说明一下,用”//”的形式来加载静态资源,表示的是省略请求方式,如果在http或https下会自动补全成http://…或https://…,由于我们要加载外部的资源并且是使用文件的形式查看的所以我们要用全路径。在page -> view -> index.html中加上:
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
接下来进行测试,在page -> index -> index.js引用jquery,即:
'use strict'; console.log('hello index'); $('body').html('hello index~~~~~ !');
执行webpack,后打开浏览器看到执行成功!
4.使用模块化的方式引入jquery
如果使用模块化的方式该如何引用jquery呢?
首先在webpack.config.js中加上external字段
externals:{ 'jquery':'window.jQuery' }
在index->index.js中修改
var $$ = require('jquery'); $$('body').html('hello index~~~~~ !');
刷新页面我们发现刚才的 hello index~~~~~ ! 还是生效的。
6. 如何创建公共模块?
CommonsChunkPlugin使我们需要用到的模块,进入它的github看到官方用法说明。我们复制一下new语句添加到配置文件中,现在做到这一步配置文件的完整代码是:
/* * @Author: shirayner * @Date: 2017-12-30 14:33:55 * @Last Modified by: shirayner * @Last Modified time: 2017-12-30 20:13:50 */ var webpack = require('webpack'); var config= { entry: { 'common': ['./src/page/common/index.js'], 'index' : ['./src/page/index/index.js'], 'login' : ['./src/page/login/index.js'] }, output: { path: './dist', filename: 'js/[name].js' }, externals:{ 'jquery':'window.jQuery' }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ name : 'common', filename : 'js/base.js' }) ] }; module.exports=config;
之后我们webpack一下,看到base.js已经进到dist中了,接下来我们来测试一下效果,在page中新建一个module.js
'use strict'; module.exports = { test:1234 }
再page -> index -> index.js 改为
require('../module.js');
再page -> login -> index.js 改为
require(‘../module.js’);
webpack一下后,进入base.js,这是我们刚才设定的通用模块的放置位置。进入后看到已经这个通用的组建进来了。
7.全局模块处理通用逻辑
接下来我们还需要一个全局的模块来处理一些通用的逻辑,比如说全局样式的引入和一些全局的处理、统计之类的。
全局模块最简单的方法是在每个页面都引用一下,但是这样会很麻烦,每个页面都要多引用一个东西。
在page中新建的common文件夹,其下创建一个common.js。
console.log(‘i am global’);
修改配置文件在entry下添加common在plugins下添加name:’common’:
'common': ['./src/page/common/index.js'],

/* * @Author: shirayner * @Date: 2017-12-30 14:33:55 * @Last Modified by: shirayner * @Last Modified time: 2017-12-30 20:13:50 */ var webpack = require('webpack'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); var config= { entry: { 'common': ['./src/page/common/index.js'], 'index' : ['./src/page/index/index.js'], 'login' : ['./src/page/login/index.js'] }, output: { path: './dist', filename: 'js/[name].js' }, externals:{ 'jquery':'window.jQuery' }, module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader","css-loader") } ] }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ name : 'common', filename : 'js/base.js' }), new ExtractTextPlugin("css/[name].css") ] }; module.exports=config;
执行webpack后看到dist下的base.js中’i am global’已经被加载进来了。
到这里我们通用模块的配置就已经完成了。
这种方法即优化了加载速度又能够提供全局的模块还免去了在每个页面中的require。这样webpack对脚本处理的问题就全部解决了。
接下来我们看看webpack对样式的处理还有什么问题?
8.处理样式使用什么loader?
首先新建一个样式文件page -> index -> index.css
body{
background:#ccc;
}
在page -> index -> index.js 引入刚才写的样式
require('./index.css');
require('../module.js');
在webpack.config.js中加上module:

/* * @Author: shirayner * @Date: 2017-12-30 14:33:55 * @Last Modified by: shirayner * @Last Modified time: 2017-12-30 20:13:50 */ var webpack = require('webpack'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); var config= { entry: { 'common': ['./src/page/common/index.js'], 'index' : ['./src/page/index/index.js'], 'login' : ['./src/page/login/index.js'] }, output: { path: './dist', filename: 'js/[name].js' }, externals:{ 'jquery':'window.jQuery' }, module: { loaders: [ { test: /\.css$/, loader: 'style-loader!css-loader' } ] }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ name : 'common', filename : 'js/base.js' }), new ExtractTextPlugin("css/[name].css") ] }; module.exports=config;
可以看到我们将在module中使用的是style loader和css loader,!连接两个loader,这个的意思是做两个loader的串联,执行顺序是从右往左,即会先执行css loader然后再用执行的结果执行style loader。接下来我们安装这两个loader并检查一下安装结果,注意开发工具的安装在后面加上–dev,在terminal中输入
npm install css-loader style-loader –save-dev
ls
cat package.json
我们可以看到css和style loader都以安装好了。执行一下webpack,看到执行成功。
接下来我们看一下css被打包到了哪里。
dist -> js -> index.js
看到css被当成了一个字符串放在js中来处理,这样虽然能够将css做模块化,但另一问题是,我们这里使用js来加载的css需要等待js加载完毕后才能够加载进来,这样会导致在加载的时候可能会出现一段空白样式的时间,这是不太能够接受的。
因此我们想办法将它放到一个单独的css文件中,使用link的形式来加载。这里我们将使用 extract-text-webpack-plugin 插件来解决这个问题,首先我们需要进行插件的安装,网上一些教程使用的是
npm install extract-text-webpack-plugin --save-dev
执行后可以看到报错了,这是因为在npm 3以上的版本不再自动寻找依赖而是需要我们自己找到合适的包,
对于我们来说该如何去找这么多的插件和loader呢?我们进入这个插件的github中看一下版本历史。
我们这里选择v1.0.1,
npm install extract-text-webpack-plugin@1.0.1 --save-dev
看到安装成功了我们修改一下配置文件:

/* * @Author: shirayner * @Date: 2017-12-30 14:33:55 * @Last Modified by: shirayner * @Last Modified time: 2017-12-30 20:13:50 */ var webpack = require('webpack'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); var config= { entry: { 'common': ['./src/page/common/index.js'], 'index' : ['./src/page/index/index.js'], 'login' : ['./src/page/login/index.js'] }, output: { path: './dist', filename: 'js/[name].js' }, externals:{ 'jquery':'window.jQuery' }, module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader","css-loader") } ] }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ name : 'common', filename : 'js/base.js' }), new ExtractTextPlugin("css/[name].css") ] }; module.exports=config;
再执行webpack,看到dist下面已经有了刚才配置的css文件夹,刚才的background已经被打包进来了。在js中也搜索不到background了,说明已经打包成功了。
在view -> index.html下应用一下css看一下效果,需要更改一下代码来引入

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="../../dist/css/index.css"> </head> <body> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script> <script type="text/javascript" src="../../dist/js/base.js"></script> <script type="text/javascript" src="../../dist/js/index.js"></script> </body> </html>
如果用的sublime的话,右键空白区域,open in browser打开浏览器看到背景已经变成灰色了,ctrl+i可以看到i am global也进来了