Welcome to my blog to read: “Original recipe:” wechat small program support NPM”

Wechat applet itself does not support the use of NPM package. At present, many frameworks on the market also have corresponding solutions.

The purpose of this article is to provide a solution for those of you (like me) who don’t want to introduce third-party frameworks and want to write native code in a small program environment.

In modern Web development, We are all too familiar with Webpack, which simply means that before a project is published, all the resources are packaged, and then an entry file is provided, which is imported into the entry template.

So my idea is to use Webpack to package all our NPM dependencies and provide an entry file through which we can use NPM dependencies in applets.

This is what we’re going to end up with.

For example, in the home page of our small program, we need to use the moment

Pages/home/home. Js:

const { moment } require('.. /npm/index');
const time = moment();
Copy the code

Webpack packs NPM dependencies

The default output of Webpack, bundle.js, is a closure that executes immediately, as follows:

Using webpack.config.js configuration:

const path = require('path');

module.exports = {
  entry: './foo.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'}};Copy the code

Run the bundle.js generated by $webpack:

(function(modules) { 

  // webpackBootstrap

})([module1, module2, module3]);
Copy the code

The sample code: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step1

This code, obviously, does not achieve the desired effect. Fortunately, WebPack provides a configuration item for Output.libraryTarget.

output.libraryTarget: “commonjs2”

For output.libraryTarget: “commonjs2”

The return value of your entry point will be assigned to the module.exports.

By configuring this property, we can ensure that the bundle.js bundled with WebPack is modular. Of course output.libraryTarget has other options, you can check the official document.

For example, using the webpack.config.js configuration:

const path = require('path');

module.exports = {
  entry: './foo.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'.libraryTarget: 'commonjs2',}};Copy the code

Run the bundle.js generated by $webpack:

module.exports = (function(modules) { 

  // webpackBootstrap

})([module1, module2, module3]);
Copy the code

The sample code: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step2

In this way, we can use NPM dependencies by requiring (‘bundle.js’). From there, we can build a portal that uses NPM dependencies.

Build the NPM entrance

Create the entry file: npm.js

const momennt = require('moment');

module.exports = {
    momennt,
};
Copy the code

Configuration file: webpack.config.js

const path = require('path');

module.exports = {
    entry: './entry.js'.output: {
        path: path.resolve(__dirname, 'npm'),
        filename: 'index.js'}};Copy the code

Run $webpack and print./ NPM /index.js.

. ├ ─ ─ entry. Js ├ ─ ─ NPM │ └ ─ ─ index. The js └ ─ ─ webpack. Config. JsCopy the code

The sample code: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step3

For the clunky approach, just copy NPM /index.js into your project and use the contents of the NPM package you introduced.

If you use build tools in your project, you can incorporate the task of “webpack NPM” into your build process.

I use GULp to do my project building work. Here is a gulp based implementation for reference.

Combined with Gulp to do project engineering

Project Catalog:

. ├ ─ ─ dist │ ├ ─ ─ NPM │ │ └ ─ ─ index. The js │ └ ─ ─ pages │ └ ─ ─ home │ └ ─ ─ home. Js ├ ─ ─ gulpfile. Js └ ─ ─ the SRC ├ ─ ─ NPM │ └ ─ ─ Index. Js └ ─ ─ pages └ ─ ─ home └ ─ ─ home. JsCopy the code

Gulpfile does two things:

  1. Compile SRC js files to dist directory via Babel (ignore other WXML, WXSS files in the example)
  2. thenpm/index.jsPackage to via Webpackdist/npm/index.jsAnd compress.

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(),
    ],
};

// Clear the./dist directory
gulp.task('clean', () => del(['./dist/**']));

// Package NPM dependencies
gulp.task('npm', () => {
    gulp.src('./src/npm/*.js')
        .pipe(webpackStream(webpackConfig), webpack)
        .pipe(gulp.dest('./dist/npm'));
});

// Compile the JS file
gulp.task('scripts', () => {
    gulp.src(['./src/**/*.js'.'! ./src/npm/*.js'])
        .pipe(babel({
            presets: ['stage-0'.'es2015'],
        }))
        .pipe(gulp.dest('./dist'));
});

// Development mode command
gulp.task('build'['clean'], () => runSequence('scripts'.'npm'));
Copy the code

The sample code: https://github.com/JerryC8080/use-npm-in-weapp/tree/master/step4

About controlling NPM file code volume

Wechat limits the code amount of the project to 2M. Even if the subcontracting mechanism is used, the maximum code amount is 4M. A single moment library, even if compressed, would require over 200 kilobytes, which is not very friendly to our code volume. We need to be very careful with the introduction of NPM, measure the size of each dependency package, and reduce the amount of code that depends on it in any way possible. For moment, we can use moment-mini instead, which only needs 51KB when compressed.

And I think putting NPM dependencies in an entry file gives us a global view of NPM dependencies.