There are some doubts about using SaveDefinitions (1), (2), so let's implement a brute force approach which may be later used automatically.
Outline
Needs @ yourPackage (*a*) CDFDeploy @ With[ { source = Import[packagePath] (*b*) } , DynamicModule[ { ... } , ... , Initialization :> ( Get @ StringToStream @ source ) ] - (a). You have to call you package before creating
DynamicModulebecause you need all static content (not held/dynamic) in the body ofDMto be parsed and evaluated properly.
And all dynamic/held names to be "typeset" with proper context name. And they will be found thanks to $ContextPath modified by BeginPackage and friends. (3)
(b). We have to use
Withto inject source intoDynamicModule's InitializationbecauseInitializationis set withRuleDelayedwhich isHoldRest.For more complex/time consuming packages you may want to change
SynchronousInitialization->Falseand monitor the state of initialization analogously to:
Working with DynamicModule: Tracking the progress of Initialization
###Execution
First code block is only to create a test package:
content = " BeginPackage[\"TestPackage`\"] f::usage=\"f[x] returns a plot.\"; Begin[\"`Private`\"] f[x_]:=Plot[Sin[x y],{y,0,2 Pi},PlotRange->{-1,1},ImageSize->500] End[] EndPackage[]"; path = FileNameJoin[{$TemporaryDirectory, "package.m"}]; pathEnc = FileNameJoin[{$TemporaryDirectory, "package.enc"}]; pathCDF = FileNameJoin[{$TemporaryDirectory, "CDF.cdf"}] Export[path, content, "Text"]; Now the actual code:
Encode[path, pathEnc]; (*c*) encodedpackage = Import[pathEnc, "Text"]; Get @ pathEnc (*a*) CDFDeploy[ pathCDF, #, Method -> "Standalone", "Target" -> "CDFPlayer" ] & @ With[ { source = encodedpackage (*b*) } , DynamicModule[{x = 1} , Column[{ Dynamic[{x, f[x]}], Button["x++", x++], Dynamic @ $ContextPath }] , Initialization :> Module[{stream} , stream = StringToStream @ source ; Get @ stream ; Close @ stream ] ] ] c. we are Encoding source, it is then obscure for others and already compressed so why not. You can even incorporate password protection with this method: (4). It won't be fully secure, as pointed in comments here: (5).
You can now go to the CDF and test in the FreePlayer:
SystemOpen @ DirectoryName @ pathCDF 
###Links
(1) The dangers of SaveDefinitions
(2) Not FullDefinition for Save. MachineID not Protected?
(3) load a Mathematica package inside a DynamicModule
(4) Encode->Import->StringToStream->Get on password-locked stream
(5) How to create protected single-file stand-alone CDF applications