|
微信小程序本身不支持 npm 包的使用,目前市面上很多框架也有了相對(duì)應(yīng)的解決方案。 本文旨在為那些不愿意引入第三方框架, 想在小程序環(huán)境中寫(xiě)原汁原味代碼的人(例如我),提供一種解決問(wèn)題的思路。 在現(xiàn)代的 Web 開(kāi)發(fā)中,我們對(duì) Webpack 已經(jīng)再熟悉不過(guò)了,簡(jiǎn)單理解,它就是項(xiàng)目發(fā)布之前,把所有資源都打包好,然后提供一個(gè)入口文件,在入口模板中引入這個(gè)入口文件。 那么我的思路,就是利用 Webpack 把我們所有的 npm 依賴(lài)打包好,提供一個(gè)入口文件,在小程序開(kāi)發(fā)中,我們通過(guò)這個(gè)入口文件,進(jìn)而使用 npm 的依賴(lài)。 我們最終實(shí)現(xiàn)的效果應(yīng)該是這樣的。 例如我們小程序的首頁(yè)中,需要使用到 moment pages/home/home.js:
const { moment } require('../npm/index');
const time = moment();
Webpack 打包 npm 依賴(lài)webpack 默認(rèn)輸出的 bundle.js ,是一個(gè)立即執(zhí)行的閉包,如以下: 使用 webpack.config.js 配置:
const path = require('path');
module.exports = {
entry: './foo.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
運(yùn)行 $ webpack 生成的 bundle.js :
(function(modules){
// webpackBootstrap
})([module1, module2, module3]);
示例代碼: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step1 這樣的代碼,顯然沒(méi)法達(dá)到我們要的效果。 幸好 webpack 提供了 output.libraryTarget 的配置項(xiàng)。 output.libraryTarget: “commonjs2”對(duì)于 output.libraryTarget: "commonjs2" 官方解釋?zhuān)?/p> The return value of your entry point will be assigned to the module.exports. 通過(guò)配置該屬性,我們能保證 webpack 打包出來(lái)的 bundle.js ,是模塊化的。 當(dāng)然 output.libraryTarget 還有其他的選項(xiàng)值,可以查閱 官方文檔 。 例如,使用 webpack.config.js 配置:
const path = require('path');
module.exports = {
entry: './foo.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
libraryTarget: 'commonjs2',
}
};
運(yùn)行 $ webpack 生成的 bundle.js :
module.exports = (function(modules){
// webpackBootstrap
})([module1, module2, module3]);
示例代碼: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step2 這樣,我們就可以通過(guò) require('bundle.js') , 來(lái)使用 npm 依賴(lài)了。 在這個(gè)基礎(chǔ)上,我們就可以打造一個(gè)使用 npm 依賴(lài)的入口。 打造 npm 入口建立入口文件:npm.js
const momennt = require('moment');
module.exports = {
momennt,
};
配置文件:webpack.config.js
const path = require('path');
module.exports = {
entry: './entry.js',
output: {
path: path.resolve(__dirname, 'npm'),
filename: 'index.js'
},
};
運(yùn)行 $ webpack ,輸出 ./npm/index.js 打包文件,對(duì)應(yīng)的目錄: . ├── entry.js ├── npm │ └── index.js └── webpack.config.js 示例代碼: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step3 笨拙點(diǎn)的方法,你只需要把 npm/index.js 拷貝到你的項(xiàng)目中,就可以使用你所引入的 npm 包的內(nèi)容了。 如果你的項(xiàng)目中使用了構(gòu)建工具的話,就可以把「 webpack 打包 npm」 的這項(xiàng)任務(wù)加入到你的構(gòu)建流程中。 我是使用 gulp 來(lái)做項(xiàng)目構(gòu)建工作的,下面提供一種基于 gulp 的實(shí)現(xiàn)作為參考。 結(jié)合 Gulp 做項(xiàng)目工程化工程目錄:
.
├── dist
│ ├── npm
│ │ └── index.js
│ └── pages
│ └── home
│ └── home.js
├── gulpfile.js
└── src
├── npm
│ └── index.js
└── pages
└── home
└── home.js
而 gulpfile 負(fù)責(zé)兩件事:
gulpfile.js:
const gulp = require('gulp');
const babel = require('gulp-babel');
const del = require('del');
const runSequence = require('run-sequence');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const webpackConfig = {
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: ['es2015'],
},
}],
},
output: {
filename: 'index.js',
libraryTarget: 'commonjs2',
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
],
};
// 清空 ./dist 目錄
gulp.task('clean', () => del(['./dist/**']));
// 打包 npm 依賴(lài)
gulp.task('npm', () => {
gulp.src('./src/npm/*.js')
.pipe(webpackStream(webpackConfig), webpack)
.pipe(gulp.dest('./dist/npm'));
});
// 編譯 JS 文件
gulp.task('scripts', () => {
gulp.src(['./src/**/*.js', '!./src/npm/*.js'])
.pipe(babel({
presets: ['stage-0', 'es2015'],
}))
.pipe(gulp.dest('./dist'));
});
// 開(kāi)發(fā)模式命令
gulp.task('build', ['clean'], () => runSequence('scripts', 'npm'));
示例代碼: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step4 關(guān)于控制 npm 文件代碼量微信限制了項(xiàng)目的代碼量為 2M,就算使用了分包機(jī)制,最多也是 4M 的代碼量。 區(qū)區(qū)一個(gè) moment 庫(kù)的話,就算壓縮過(guò),也需要兩百多 KB,這對(duì)于我們的代碼量,是很不友好的。 我們需要對(duì) npm 的引入持非常謹(jǐn)慎的態(tài)度,去度量每個(gè)依賴(lài)包的大小,想盡各種辦法減少依賴(lài)的代碼量。 譬如 moment 我們可以使用 moment-mini 來(lái)代替,后者壓縮過(guò)后只需要 51KB。 而且我認(rèn)為把 npm 的依賴(lài)放在一個(gè)入口文件中,會(huì)讓我們可以對(duì) npm 的依賴(lài)有一個(gè)全局的把握。 |