我第一次尝试使用 webpack 时遇到了困难。

我在浏览器控制台中收到以下错误。

ERROR TypeError: $(...).sparkline is not a function 

这是我的 webpack.config.vendor.js 代码

const path = require('path'); 
const webpack = require('webpack'); 
//const ExtractTextPlugin = require('extract-text-webpack-plugin'); 
const merge = require('webpack-merge'); 
 
const treeShakableModules = [ 
    '@angular/animations', 
    '@angular/common', 
    '@angular/compiler', 
    '@angular/core', 
    '@angular/forms', 
    '@angular/http', 
    '@angular/platform-browser', 
    '@angular/platform-browser-dynamic', 
    '@angular/router', 
    'zone.js/dist/zone', 
]; 
const nonTreeShakableModules = [ 
    'jquery', 
    'jquery-sparkline', 
    '.\\node_modules\\jquery-sparkline\\jquery.sparkline.js', 
     '@angular/material', 
    'event-source-polyfill', 
    '.\\wwwroot\\assets\\styles\\style.scss', 
    '.\\node_modules\\chartist\\dist\\chartist.css', 
    '.\\node_modules\\quill\\dist\\quill.snow.css', 
    '.\\node_modules\\quill\\dist\\quill.bubble.css', 
    '.\\node_modules\\angular-calendar\\css\\angular-calendar.css', 
    '.\\node_modules\\dragula\\dist\\dragula.css', 
    '.\\ClientApp\\styles.css', 
]; 
const allModules = treeShakableModules.concat(nonTreeShakableModules); 
 
module.exports = (env) => { 
 
    const isDevBuild = !(env && env.prod); 
    const sharedConfig = { 
        stats: { "modules": true  
             }, 
        resolve: { 
            extensions: ['.js'], 
        }, 
        module: { 
            rules: [ 
                { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' } 
            ] 
        }, 
        output: { 
            publicPath: 'dist/', 
            filename: '[name].js', 
            library: '[name]_[hash]' 
        }, 
        plugins: [ 
            new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) 
            new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580 
            new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898 
            new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)esm5/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/20357 
            new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100 
        ] 
    }; 
 
    const clientBundleConfig = merge(sharedConfig, { 
        entry: { 
            // To keep development builds fast, include all vendor dependencies in the vendor bundle. 
            // But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle. 
            vendor: isDevBuild ? allModules : nonTreeShakableModules 
        }, 
        output: { path: path.join(__dirname, 'wwwroot', 'dist') }, 
        module: { 
            rules: [ 
                { 
                    test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] 
                }, 
                { 
                    test: /\.css$/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize'] 
                }, 
                //{ 
                    //test: /\.scss$/, use: ExtractTextPlugin.extract({ 
                    //    use: ['css-loader', 'sass-loader'], 
                    //    // use style-loader in development 
                    //    fallback: "style-loader" 
                    //}) 
                //} 
            ] 
        }, 
        plugins: [ 
            new webpack.DllPlugin({ 
                context: __dirname, 
                path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'), 
                name: '[name]_[hash]' 
            }) 
        ].concat(isDevBuild ? [] : [ 
            new webpack.optimize.UglifyJsPlugin() 
        ]) 
    }); 
 
    const serverBundleConfig = merge(sharedConfig, { 
        target: 'node', 
        resolve: { mainFields: ['main'] }, 
        entry: { vendor: allModules.concat(['aspnet-prerendering']) }, 
        output: { 
            path: path.join(__dirname, 'ClientApp', 'dist'), 
            libraryTarget: 'commonjs2', 
        }, 
        module: { 
 
            rules: [ 
                { 
                    test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] 
                }, 
                { 
                    test: /\.css$/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize'] 
                }, 
                //{ 
                //test: /\.scss$/, use: ExtractTextPlugin.extract({ 
                //    use: ['css-loader', 'sass-loader'], 
                //    // use style-loader in development 
                //    fallback: "style-loader" 
                //}) 
                //} 
            ] 
        }, 
        plugins: [ 
            new webpack.DllPlugin({ 
                context: __dirname, 
                path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'), 
                name: '[name]_[hash]' 
            }) 
        ] 
    }); 
 
    return [clientBundleConfig, serverBundleConfig]; 
} 

这是我的 webpack.config.js 代码。

const path = require('path'); 
const webpack = require('webpack'); 
const merge = require('webpack-merge'); 
const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin; 
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; 
const ExtractTextPlugin = require('extract-text-webpack-plugin'); 
 
module.exports = (env) => { 
    // Configuration in common to both client-side and server-side bundles 
    const isDevBuild = !(env && env.prod); 
    const sharedConfig = { 
        stats: { modules: true }, 
        context: __dirname, 
        resolve: { extensions: ['.js', '.ts'] }, 
        output: { 
            filename: '[name].js', 
            publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix 
        }, 
        module: { 
            rules: [ 
                { 
                    test: /\.ts$/, use: isDevBuild ? ['awesome-typescript-loader?silent=true', 'angular2-template-loader', 'angular2-router-loader'] : '@ngtools/webpack' 
                }, 
                { 
                    test: /\.html$/, use: 'html-loader?minimize=false' 
                }, 
                { 
                    test: /\.css$/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize'] 
                }, 
                //{ 
                //    test: /\.scss$/, use: ExtractTextPlugin.extract({ 
                //        use: ['css-loader', 'sass-loader'], 
                //        // use style-loader in development 
                //        fallback: "style-loader" 
                //    }) 
                //}, 
                { 
                    test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] 
                }, 
                { 
                    test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' 
                } 
            ] 
        }, 
        plugins: [ 
            new ExtractTextPlugin({ filename: 'vendor.css', disable: false, allChunks: true }), 
            new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) 
            new CheckerPlugin() 
        ] 
    }; 
 
    // Configuration for client-side bundle suitable for running in browsers 
    const clientBundleOutputDir = './wwwroot/dist'; 
    const clientBundleConfig = merge(sharedConfig, { 
        entry: { 
            'main-client': './ClientApp/boot.browser.ts' 
        }, 
        output: { path: path.join(__dirname, clientBundleOutputDir) }, 
        plugins: [ 
            new webpack.DllReferencePlugin({ 
                context: __dirname, 
                manifest: require('./wwwroot/dist/vendor-manifest.json') 
            }) 
        ].concat(isDevBuild ? [ 
            // Plugins that apply in development builds only 
            new webpack.SourceMapDevToolPlugin({ 
                filename: '[file].map', // Remove this line if you prefer inline source maps 
                moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk 
            }) 
        ] : [ 
                // Plugins that apply in production builds only 
                new webpack.optimize.UglifyJsPlugin(), 
                new AngularCompilerPlugin({ 
                    tsConfigPath: './tsconfig.json', 
                    entryModule: path.join(__dirname, 'ClientApp/app/components/app.browser.module#AppModule'), 
                    exclude: ['./**/*.server.ts'] 
                }) 
            ]) 
    }); 
 
    // Configuration for server-side (prerendering) bundle suitable for running in Node 
    const serverBundleConfig = merge(sharedConfig, { 
        resolve: { mainFields: ['main'] }, 
        entry: { 'main-server': './ClientApp/boot.server.ts' }, 
        plugins: [ 
            new webpack.DllReferencePlugin({ 
                context: __dirname, 
                manifest: require('./ClientApp/dist/vendor-manifest.json'), 
                sourceType: 'commonjs2', 
                name: './vendor' 
            }) 
        ].concat(isDevBuild ? [] : [ 
            // Plugins that apply in production builds only 
            new AngularCompilerPlugin({ 
                tsConfigPath: './tsconfig.json', 
                entryModule: path.join(__dirname, 'ClientApp/app/app.server.module#AppModule'), 
                exclude: ['./**/*.browser.ts'] 
            }) 
        ]), 
        output: { 
            libraryTarget: 'commonjs', 
            path: path.join(__dirname, './ClientApp/dist') 
        }, 
        target: 'node', 
        devtool: 'inline-source-map' 
    }); 
 
    return [clientBundleConfig, serverBundleConfig]; 
}; 

我已经包含了 jquery-sparkline,但我仍然收到该错误。我可以在 vendor.js 中看到迷你图代码,但它似乎没有任何区别。

我还查看了 vendor list 文件,它包含这个但没有提到迷你图。

"./node_modules/jquery-sparkline/jquery.sparkline.js":{ 
         "id":101, 
         "meta":{ 
 
         } 
      } 

我也不明白为什么我必须将下面的 ProvidePlugin 放在两个文件中。当然一次应该足够了,但是当它只在 vendor 文件中时,我收到浏览器错误,说它找不到 $。

new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }) 

如有任何帮助,我们将不胜感激!

谢谢

请您参考如下方法:

看起来您正在使用 angular-netcore。

在这种情况下,您需要为迷你图安装types,因为还没有准备好,您必须创建一个。

ClientApp/typings/sparkline/index.d.ts

index.d.ts

// Generated by typings 
// Source: ClientApp/typings/sparkline/index.d.ts 
interface JQuery { 
    sparkline(values?: string | Array<(string | number)>, opts?: sparkline.Settings): any; 
} 
 
declare namespace sparkline { 
    interface Settings { 
        type?: string; 
        barColor?: string; 
        width?: string | number; 
        height?: string; 
        lineColor?: string; 
        fillColor?: string | number; 
        chartRangeMin?: string | number; 
        chartRangeMax?: string | number; 
        composite?: boolean; 
        enableTagOptions?: boolean; 
        tagOptionPrefix?: string; 
        tagValuesAttribute?: string; 
        disableHiddenCheck?: boolean; 
    } 
} 

接下来你需要向全局声明:

typings install --global --save file:./ClientApp/typings/sparkline/index.d.ts   

如果你没有typings,你可以安装

yarn install typings 

最后将 jquery-sparkline 添加到 boot.browser.ts

boot.browser.ts

import 'reflect-metadata'; 
import 'zone.js'; 
import 'bootstrap'; 
import 'jquery-sparkline'; 
import { enableProdMode } from '@angular/core'; 
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app/app.browser.module'; 
... 

因为 boot.browser.ts 是客户端包的配置,适合在浏览器中运行。

!!!重要

不要将 import 'jquery-sparkline'; 放入应用程序/组件,因为我们不想注入(inject)到 boot.server (会抛出错误原因服务器端预渲染)。

此处需要完整的代码示例:dotnet-core-angular-sparkline


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!