代码接着上一章webpack学习笔记(二)环境分离+多页面开发配置
各种基于mvc、mvvm框架的出现,单纯的jq已不适合这样的开发了,但如果是不使用框架的项目,使用jq总比写原生好吧0.0
既然都使用了webpack来开发,就不要使用来引入
npm i -D jquery
然后回到index.js
文件,通过require('jquery')
引入jquery
,顺便在index.html
里面随便写点什么(前面两章写的已删除)
/* index.js */
import '../style/index.css';
import '../style/less.less';
import '../style/scss.scss';
import '../style/sass.sass';
const $ = require('jquery');
console.log($);
console.log($('#J-demo1').html());
$('#J-btn1').click(function () {
alert('hello');
});
/* index.html */
webpack学习笔记(三)
引入jquery
npm start
运行可看到相关jquery
的功能都已实现,$
也被打印出来,但是你在控制台打印$
jQuery
就会发现$
并不是上述打印的$
,jQuery
也会报错jQuery is not defined
,说明我们使用的$
jQuery
不是全局属性
顾名思义,解析某个模块,然后暴露出去,如果不想使用全局属性那也就按照上述那样吧,但若将其设置为全局需要使用expose-loader
来解析相应的模块,然后在webpack.js
中添加其配
npm i -D expose-loader
/* webpack.js */
{
// 通过require('jquery')来引入
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
// 暴露出去的全局变量的名称 随便你自定义
options: 'jQuery'
},
{
// 同上
loader: 'expose-loader',
options: '$'
}
]
}
跑起来,控制台打印$
jQuery
,它们已属于全局变量,如果上述代码中的options
值你自定义了的话,打印你的自定义名称,其就是jQuery
方法,之后你可以在以index.js
作为入口文件的任意.js
文件里面调用$
jQuery
在单页面开发中是否提取公共模块意义不大,但在多页面运用中就需要提取了,上一章中我们创建了index.html
demo1.html
demo2.html
三个页面,也创建了同名的三个入口js文件,就拿上述的jQuery中,如果三个页面都需要使用呢?我们在三个入口文件里面引入jquery
,查看打包结果,我们就写了几行代码,由于引入了jquery
导致三个文件大小倍增
使用CommonsChunkPlugin
插件来提取公共模块,webpack
中已集成了改插件,只需要调用即可,我们在webpack.prod.js
里面使用该插件
/* webpack.prod.js */
...
new webpack.optimize.CommonsChunkPlugin({
// 提取出公共模块的chunkName,在html-webpack-plugin插件使用该chunkName
name: 'commons',
// 生成的公共模块文件路径和文件名 [name]是其chunkName 即commons
filename: 'static/js/[name].[hash].js',
// 模块被引用的最小次数,低于该次数将不会被提取
minChunks: 3
})
...
但是目前只是提取出来,html里面并没有通过来引入,我们已经知道公共模块其chunkName为commons,这就好办啦,修改
webpack.js
中html-webpack-plugin
配置即可,然后打包运行,html中也就引入了公共模块
/* webpack.js */
...
config.pageNames.forEach((page) => {
const htmlPlugin = new HtmlWebpackPlugin({
filename: `${page}.html`,
template: path.join(__dirname, `../src/page/${page}.html`),
// chunkName集合,page为当前入口文件chunkName commons为公共模块chunkName
chunks: [page, 'commons']
});
HtmlPlugins.push(htmlPlugin);
Entries[page] = path.join(__dirname, `../src/script/${page}.js`);
});
...
目前这种做法有一个缺点,那就是引用次数大于等于3的文件都会被打包进入公共模块,也就是说A页面其多个(大于等于3)子项模块引入了某个tool.js
模块,然而B页面没有使用这个模块,tool.js
这个模块也依然会被打包进入公共模块,然后被A、B两个页面加载,要解决这个问题就需要代码分割、按需加载,我们后续再提
前提条件—了解ejs
语法ejs传送门
在开发过程中肯定会遇到一些公用,或者使用数据来渲染的模块,我们可以将这些模块制作成模版,传入指定参数来渲染,首先先下载 ejs-loader
,用它来解析我们的模版,然后我们在src
下面创建一个tpl
文件夹并创建一个头部模版
npm i -D ejs-loader
模版的路口同样是.js
文件,通过其来引入样式或者html文件(这里创建不能起名叫.html,因为之前已经使用过对应的loader,否则会出错),你可以将其命名为.ejs
.tpl
.tem
都行,只需要后缀不冲突即可,我们在外部引入该模版之后打印一下这个tpl
,这里需要先在webpack.js
里面加入对.tpl
文件的解析,使用ejs-loader
/* webpack.js */
...
{
// 对模版文件使用loader
test: /\.tpl$/,
use: 'ejs-loader'
}
...
控制台看结果
可以看到我们的通过import
引入的tpl
其实是一个函数,返回值是字符串类型的html
语句,我们可以将返回值通过节点操作挂到DOM树上,并且我们也可以看到该函数需要传入一个对象参数tpl({namex: xxx, sex: xx})
,如果是富文本的话也是支持传入,并不需要<%- xxx %>
的写法,如下图栗子
使用ejs
的语法我们就能自由的创建字符串模版,这样就不再需要字符串拼接啦~
tpl模版的基础原理就是这样,剩下的就自行慢慢进行各种骚操作吧,你可以把模版当作一个沙盒,数据都由外部传入,也可以反过来行之,怎么方便怎么来就好~
到目前为止,算上前面两章,基础的webpack
配置结构已经搞定,接下来加上一点点瓦片,让其能住得下人
该项功能只适合开发环境,并且是和webpack-dev-server
配套的,只需要在wepback.js
加入devServer
属性并传入相应的值,我们在config
中定义端口号和局域网IP即可
/* config.js */
module.exports = {
...
// 开发
dev: {
sourceMap: true,
extract: false,
// 局域网IP
host: '192.168.11.105',
// 端口号
port: '2018'
}
...
};
/* webpack.js */
module.exports = {
...
devServer: {
host: config.dev.host,
port: config.dev.port
}
...
}
webpak
提供了现实百分比进度的命令--progress
,我们只需要在package.json
修改即可
/* package.json */
"scripts": {
"start": "nodemon --watch build/ --exec \"webpack-dev-server --progress --config build/webpack.dev.js\"",
"build": "webpack --progress --config build/webpack.prod.js"
}
目前我也就只完成到这里,剩下的代码分割,按需加载,HMR等功能都也还在构建中,之后的笔记再提~
依旧附上本章GitHub源码